![f9096a3529ee9fdab825b22916ac1f68.gif](https://img-blog.csdnimg.cn/img_convert/f9096a3529ee9fdab825b22916ac1f68.gif)
垃圾回收本身可以利用多个CPU的存在并并行执行。尽管在此期间应用程序线程保持完全挂起,但垃圾回收可以在短时间内完成,从而有效地减少了挂起时间。
第二种方法是保持应用程序运行,并在应用程序执行的同时执行垃圾回收。
![184db79cdcff821940194d8f062038be.png](https://img-blog.csdnimg.cn/img_convert/184db79cdcff821940194d8f062038be.png)
(大部分)并发标记和清扫
并发垃圾收集策略使相对简单的标记清除算法变得有些复杂。标记阶段通常分为以下几种变体:在初始标记中,GC根对象标记为活动。在此阶段,应用程序的所有线程都被挂起。
在并发标记期间,将遍历已标记的根对象,并标记所有可到达的对象。此阶段与应用程序执行完全并发,因此所有应用程序线程都处于活动状态,甚至可以分配新对象。因此,可能会有另一个阶段来标记在并行标记期间已分配的对象。有时将其称为预清理,并且仍与应用程序执行同时进行。
在最后的标记中,所有线程都被挂起,所有剩余的新分配的对象都标记为活动。这在图2.6中用重新标记标签指示。
由于标记阶段与应用程序的执行同时进行,因此为对象分配的空间可能会超过CMS的容量,从而导致分配错误。
空闲列表立即导致内存碎片,所有这些都导致了。
该算法比其他两种算法更复杂,因此需要更多的CPU周期。
与其他方法相比,该算法需要更精细的调整并具有更多的配置选项。
减少压实的影响
现代垃圾收集器利用多个CPU并行执行其压缩过程。不过,在此过程中,几乎所有人都必须暂停应用程序。具有数GB内存的JVM可以挂起几秒钟或更长时间。要解决此问题,各种JVM各自实现一组参数,这些参数可用于以较小的增量步骤压缩内存,而不是将其作为一个大块。参数如下:压缩不是针对每个GC周期执行的,而是仅在达到一定碎片级别时执行的(例如,如果50%以上的可用内存不连续)。
可以配置目标分段。垃圾收集器不会压缩所有内容,而只会压缩直到指定百分比的可用内存作为连续块可用为止。
![7e10f18dc626fa193f29e6e151e00a7e.png](https://img-blog.csdnimg.cn/img_convert/7e10f18dc626fa193f29e6e151e00a7e.png)
- 关注Java架构师Carl -
![6ef262c045ee5a5850f9098aec6a2640.gif](https://img-blog.csdnimg.cn/img_convert/6ef262c045ee5a5850f9098aec6a2640.gif)
![3c47cfbfbedf49b827c8fb1469643f57.gif](https://img-blog.csdnimg.cn/img_convert/3c47cfbfbedf49b827c8fb1469643f57.gif)
![29de98d38b8dbf07b7c92f21c96e2f2e.gif](https://img-blog.csdnimg.cn/img_convert/29de98d38b8dbf07b7c92f21c96e2f2e.gif)