简介JVM的Serial及ParNew收集器

Serial:

串行收集器,JVM client模式下的默认收集器,使用复制算法,在进行垃圾回收时会暂停其他所有的工作线程(stop the world,简称STW)直至回收结束,因此会影响用户的正常使用体验,但是因为少了多线程切换的开销,相较于其他收集器能够更加专注于垃圾回收,在单核场景下效率极高,并且在回收较小内存(几十或者一两百兆)时,停顿时间是毫秒级的。推荐使用场景:年轻代占用几十兆到一两百兆的桌面应用。

使用方式:-XX:+UseSerialGC,打开该开关后,使用Serial(年轻代)+Serial Old(老年代) 组合进行GC。


ParNew:

并行收集器,Serial的多线程版本,使用多条线程进行垃圾回收,其他特性与Serial一致。需要注意的是,ParNew在单核甚至双核环境下绝对不会有比Serial收集器更好的效果,但是随着CPU数量的增加ParNew相较于Serial的优势会越来越明显,但并不是成倍增长的,原因还是那个,多线程切换开销。

另外ParNew用于垃圾回收的线程可用参数-XX:ParallelGCThreads=n进行配置。建议n与主机逻辑cpu数一致。

使用方式:-XX:+UseParNewGC,打开该开关后,使用ParNew(年轻代)+Serial Old(老年代)组合进行GC。另外,ParNew是CMS收集器的默认年轻代收集器。


简单比较下两款收集器的使用效果,测试结果直接写在注释:

/**
 * 测试比较Serial及ParNew两个收集器
 * -Xms2048m -Xmx2048m -XX:+PrintGCDetails -XX:+PrintFlagsFinal
 * 
 * -XX:+UseSerialGC
 * gctime:100次,耗时107.640ms
 *  
 * -XX:+UseParNewGC
 * 测试机逻辑cpu个数为4
 * ParallelGCThreads=4
 * gctime:100次,耗时59.583ms
 * ParallelGCThreads=3
 * gctime:100次,耗时77.294ms
 * ParallelGCThreads=1
 * gctime:100次,耗时137.109ms
 * ParallelGCThreads=5(可以超过主机逻辑cpu个数,但好像并没有意义)
 * gctime:100次,耗时76.557ms
 * 
 * 测试结论:逻辑cpu的个数越多,ParNew相比Serial收集器的优势会越明显,但并不是成倍增长的,因为线程之间的频繁切换会消耗一定时间,因此,单核cpu,甚至双核cpu下Serial是要优于ParNew的
 * 另外,ParallelGCThreads配成与主机逻辑cpu个数一致,效果是最好的。
 * @author ljl
 */
public class TestSerialVSParNew {
	private static int _10MB = 10 * 1024 * 1024;

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 500; i++) {
			//不断往Eden区分配对象,触发minorGC
			byte[] memory = new byte[10 * _10MB];
			Thread.sleep(100);
		}
	}
}




你可能感兴趣的:(jvm)