1. 最常用的新生代垃圾回收器: ParNew
在没有G1垃圾回收器之前,线上系统使用的都是ParNew垃圾回收器作为新生代的垃圾回收器。
即使现在有了G1,很多线上系统还是用的ParNew。
通常运行在服务器上的Java系统,都可以充分利用服务器的多核CPU的优势。假设你的服务器是4核CPU,如果对新生代垃圾回收的时候,仅仅使用单线程进行垃圾回收,就会导致没法充分利用CPU资源。
如上图,现在在垃圾回收的时候,都把系统程序所有的工作线程全部停掉了,就一个垃圾回收线程在运行。
那么此时4核CPU的资源根本没法充分利用,理论上4核CPU可以支持4个垃圾回收线程并行执行,可以提升4倍的性能!
所以说,新生代的ParNew垃圾回收器主打的就是多线程垃圾回收机制,另外一种Serial垃圾回收器主打的是单线程垃圾回收,他们俩都是回收新生代的,唯一的区别就是单线程和多线程的区别,但是垃圾回收算法是完全一样的。
如上图,ParNew垃圾回收器在合适的时机执行Minor GC的时候,就会把系统程序的工作线程全部停掉,禁止程序继续运行创建新的对象,然后自己就用多个垃圾回收线程去垃圾回收,回收的机制和算法就跟之前说的是一样的。
2. 如何为线上系统指定使用ParNew垃圾回收器?
在启动系统的时候如果要指定使用ParNew垃圾回收器,使用 “-XX:+UseParNewGC” 选项,只要加入这个选项,JVM启动之后对新生代进行垃圾回收的,就是ParNew垃圾回收器了。
3. ParNew垃圾回收器默认情况下的线程数量
在指定了使用ParNew垃圾回收器之后,它默认给自己设置的垃圾回收线程的数量就是跟CPU的核数是一样的。
比如线上机器用的是4核CPU,那么此时ParNew的垃圾回收线程数就会是4个线程。一般不用手动去调节。
如果一定要自己调节ParNew的垃圾回收线程数量,也是可以的,使用 “-XX:ParallerlGCThreads” 参数即可,通过它可以设置线程的数量。
4. 思考题1
主要有两个问题:
1、 到底是用单线程垃圾回收好,还是多线程垃圾回收好?
2、 到底是Serial垃圾回收器好还是ParNew垃圾回收器好?
启动系统的时候可以区分服务器模式和客户端模式,如果启动系统的时候加入 “-server” 就是服务器模式,如果加入 “-client” 就是客户端模式。
他们的区别就是,如果你的系统部署在比如4核8G的Linux服务器上,那么就应该用服务器模式,如果你的系统是运行在比如Windows上的客户端程序,那么就应该是客户端模式。
那么服务器模式和客户端模式的区别是啥?
服务器模式通常运行我们的网站系统、电商系统、业务系统、APP后台系统之类的大型系统,一般都是多核CPU。
所以此时如果要垃圾回收,那么肯定是要用ParNew更好,因为多线程并行垃圾回收,充分利用多核CPU资源,可以提升性能。
如果你的Java程序是一个客户端程序,比如类似百度云网盘的Windows客户端这种运行在Windows个人操作系统上呢?
这种操作系统很多都是单核CPU,此时如果还是用ParNew来进行垃圾回收,就会导致一个CPU运行多个线程,反而加重了性能开销,可能效率还不如单线程好。
因为单CPU运行多线程会导致频繁的线上上下文切换,有效率开销。
所以如果是类似那种运行在Windows上的客户端程序,建议采用Serial垃圾回收器,单CPU单线程垃圾回收即可,反而效率更高。
一般很少有用Java写客户端程序,主要用来构建复杂的大规模后端业务系统,所以常见的是用 “-server” 指定为服务器模式,然后配合 ParNew 多线程垃圾回收器。
以上就是单线程和多线程对垃圾回收的使用场景。