- 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加
- 915. Partition Array into Disjoint Intervals 分割数组
- 932. Beautiful Array 漂亮数组
- 940. Distinct Subsequences II 不同的子序列 II
新生代的内存分为Eden和两个Survivor的。如果系统不停的运行,最终会把Eden给塞满。
一旦Eden塞满,就会触发Minor GC,而进行垃圾回收是有专门的垃圾回收线程的,不同的内存区域会有不同的垃圾回收器 。
简单来说,就是垃圾回收线程和垃圾回收器配合起来,使用自己的垃圾回收算法,对指定的内存区域进行垃圾回收,如下图:
这里要思考,在GC的时候,我们写好的 Java系统在运行期间还能不能继续在新生代里创建新的对象了?
假设允许在GC期间,还可以继续让系统在新生代的Eden区里创建新的对象。那么,对于程序新创建的这些对象,垃圾回收器是无法去持续追踪这些对象的状态的。
并且在进行垃圾回收的过程中把新对象中的存活对象也转移到 Survivor1或Survivor2中去的想法是不可行的。
所以,在垃圾回收的过程中,同时还允许我们写的Java系统继续不停的运行在Eden里持续创建新的对象,目前来看是不合适的一件事。
JVM最大的痛点,是在垃圾回收的这个过程。
因为在垃圾回收的时候,尽可能要让垃圾回收器专心致志的工作,所以不能随便让我们的Java系统创建新对象,此时JVM会在后台直接进入 “Stop the World” 状态。
也就是说,他们会直接停止我们写的Java系统的所有工作线程,让我们写的代码不再运行。
然后让垃圾回收线程可以专心致志的进行垃圾回收的工作,如下图所示:
这样的话,就可以让我们的系统暂停运行,然后不再创建新的对象,同时让垃圾回收线程尽快完成垃圾回收的工作,就是标记和转移Eden以及Survivor2的存活对象到Survivor1中去,然后尽快一次性回收掉Eden和Survivor2中的垃圾对象,如下图:
接着垃圾回收完毕,就可以继续恢复Java系统的工作线程的运行了,然后我们的代码就可以继续运行,继续在Eden中创建新的对象
假设Minor GC要运行100ms,那么就会导致这100ms期间用户发起的所有请求都会出现短暂的卡顿,因为系统的工作线程不在运行,所以不能处理任何请求。
参考前面的案例,因为内存分配不合理,导致对象频繁进入老年代,平均七八分钟一次Full GC,而Full GC是最慢的,有的时候弄不好一次回收要进行几秒钟,甚至几十秒或几分钟。
那么一旦频繁的Full GC,就意味着系统每隔七八分钟后,会在30秒内任何用户的请求全部卡死无法处理,然后用户看到的都是系统超时之类的提示,这会让用户体验极差。
总得来说,无论是新生代GC还是老年代GC,都尽量不要让频率过高,也避免持续时间过长,避免影响系统正常运行。而这也是JVM过程中需要优化的一个重点。
在对新生代的回收,Serial垃圾回收器就是用一个线程进行垃圾回收,然后暂停系统工作线程,所以一般很少用这种方式。
而平时常用的新生代垃圾回收区是ParNew,它针对服务器一般都是多核CPU做了优化,是支持多线程去垃圾回收的,可以大幅度提升回收的性能,缩短回收的时间。大致原理图如下:
综上所述,不同的垃圾回收器会有不同的机制和原理,使用多线程或者单线程,都是有区别的。
我的代码遇到了很大的困难。我正在开发一个显示歌词和和弦的应用程序。我使用两个重叠的textview分隔了和弦和歌词。 我在这个项目中遇到的问题是音高改变功能。我尽我所能向我解释得更好: 和弦总数为12
我有一个游戏并使用 Tune 作为分析库。使用最新的 Unity (5.3.4f1) 并通过 Unity 获取 apk(无 eclipse/android studio)。 我的游戏在 Play 商店
我是一名优秀的程序员,十分优秀!