parallel gc是jdk 8及之前server模式默认的吞吐量优先收集器,采用多线程并行执行young gc(复制算法)和full gc(标记-压缩),通过stw换取高吞吐,适用于多核、批处理类场景,调优核心是平衡停顿与吞吐。

Parallel GC(吞吐量优先收集器)在JDK 8及之前是Server模式下的默认垃圾收集器,适用于多核CPU、对吞吐量要求高、可接受较长停顿时间的应用场景。它通过多线程并行执行Minor GC和Major GC,显著提升GC效率,但也会带来明显的STW(Stop-The-World)暂停,影响响应延迟。调优的核心不是“消除停顿”,而是让停顿时长与吞吐量目标达成合理平衡。
Parallel GC的典型性能特征
Parallel GC采用“复制算法”处理新生代(Young GC),使用“标记-压缩”处理老年代(Full GC)。它的行为高度依赖堆内存划分和对象生命周期分布:
- Young GC频繁但单次耗时短(通常几毫秒到几十毫秒),主要受新生代大小和对象晋升速率影响;
- Full GC较少但代价高(可能达数百毫秒甚至秒级),常由老年代空间不足、永久代/元空间溢出、显式System.gc()触发;
- GC线程数默认为CPU核心数,但超过物理核心数反而引发上下文切换开销,降低吞吐量。
关键JVM参数与调优方向
Parallel GC的调优围绕三个目标:控制GC频率、缩短单次停顿、保障应用吞吐量。以下参数需协同调整:
- -XX:+UseParallelGC:启用Parallel GC(JDK 8默认,JDK 9+需显式指定);
- -XX:ParallelGCThreads=N:设为CPU核心数(如16核建议设16),避免超线程过度占用;
- -Xms与-Xmx设为相等:防止堆动态扩容带来的额外开销和内存碎片风险;
- -XX:NewRatio=N:调整新生代占比(默认2,即老年代:新生代=2:1),若对象存活期短、分配快,可适当增大新生代(如NewRatio=1);
- -XX:MaxGCPauseMillis=XXX:仅作为软目标,Parallel GC不保证满足,但会据此反向调整新生代大小——值设过小会导致新生代被不断压缩,引发更频繁Young GC。
识别是否该换GC策略
当出现以下情况时,说明Parallel GC可能已不匹配当前负载特征:
- Full GC间隔短于10分钟,且每次回收后老年代占用率仍高于70%;
- 单次Young GC耗时持续超过50ms,或P99 GC停顿超过200ms,而业务SLA要求端到端响应
- 系统存在大量短期大对象(如批量报表导出、视频转码缓存),导致频繁晋升与老年代碎片化;
- CPU利用率长期低于40%,但GC时间占比却超10%,表明GC线程未饱和,可能是堆结构不合理而非并发能力不足。
监控与验证调优效果
必须依赖真实负载下的GC日志分析,而非静态配置估算:
- 开启日志:-Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps(JDK 8)或 -Xlog:gc*:gc.log:time,tags(JDK 10+);
- 关注指标:GC总耗时占比(10s)、Full GC次数(生产环境理想为0)、晋升失败(Promotion Failed)是否频繁;
- 配合jstat -gc
1s 实时观察Eden/Survivor使用率波动,判断是否因Survivor空间过小导致对象过早进入老年代。











