A Work in Progress

来源:互联网 发布:淘宝签约商家 编辑:程序博客网 时间:2024/05/22 19:19

    翻译自https://blogs.oracle.com/jonthecollector/a-work-in-progress
    当你执行”java…”,就会创建一些垃圾回收线程。如果你想知道有多少GC线程被创建,你可以使用

-XX:+PrintFlagsFinal -version

,然后在大量的输出结果里面找到ParallelGCThreads相关的。你会看到类似以下的结果:

uintx ParallelGCThreads := 23 {product}

    如果你看到的GC线程的数量比较大,这篇文章也许是你感兴趣的。
    GC线程的数量只是你的运行程序的平台的硬件线程数量的小部分。之前的假设是如果你在一个大型机器上运行你的程序,而且你的程序较大,那么你会需要许多GC线程。但今天并不是这样。
    拥有太多GC线程的问题在于它们不仅消耗资源(它们是线程,所以他们也有线程栈,也会消耗操作系统资源),而且他们彼此之前也可以进行处理(许多线程只是做小工作,却会带来很大的并行执行的开销,却收效甚微)

    如果你知道你的程序不需要做这么多的GC工作(GC停顿短暂且频率低),你就可以用以下的命令来设置GC线程的数量:

-XX:ParallerGCThreads=XXX

来使线程的数量较小。或者也可以用-XX:+UseSerialGC来设置使用Serial GC(Serial GC不会做多线程回收,所以也不会创建很多的GC线程)
    如果你不确定你需要多少的GC线程来回收,你可以试着使用

-XX:+UseDynamicNumberOfGCThreads(在jdk8中加入的)

在每次GC之前,会基于堆被使用的大小和运行的应用线程的数量来计算需要多少的GC线程。
    -XX:HeapSizePerGCThread=XXX 控制着在堆中每使用XXX byte大小的GC线程数量。在64位机器上,HeapSizePerGCThread的大小是85M。如果应用的线程数量是YYY,GC会选择2倍的YYY作为GC线程的数量。这2个中较大的数字会作为GC线程的数量。我承认,应用程序线程数量的伸缩会给那些有许多等待请求线程的应用带来问题,但是对其他应用来说是有意义的。
    如果UseDynamicNumberOfGCThreads 关掉,动态计算的GC线程数量不会超过GC线程的数量。
    动态计算GC线程的数量可以有效避免在每次垃圾回收之前过多的GC线程只需要处理一点点的回收工作。但是jdk8的实现仍然在启动时创建所有的GC线程。如此数以百计的GC线程会在一开始被创建,但是很少会被用到。在jdk9中做出的一个改进就是懒创建GC线程(用到时再创建)。在每次GC之前,动态计算出来的GC线程还没有全部创建好,额外的线程会被创建以满足数量的要求。
    打开 -XX:+TraceDynamicGCThreads 来看看你创建了多少GC线程。
    最后,为什么我给文章取的标题是“A Work in Progress”?选择的GC线程的数量可以被提高。而且对于一个回收过程中不同的部分也许需要不同的GC线程数量。希望以后有人可以用这些改进,这样越来越多的人就可以说“让VM去做吧”