吞吐量优先与低停顿时间是垃圾回收器设计的两大核心目标且存在天然张力:前者适合批处理等对延迟不敏感场景,后者适用于web api等交互式系统;需依业务sla选择收集器(如parallel系列偏吞吐,g1/zgc/shenandoah偏低停顿),并围绕目标调参与压测验证。

吞吐量优先和低停顿时间是垃圾回收器设计的两个核心目标,它们天然存在张力:追求高吞吐量往往需要减少 GC 频次、增大堆、使用并行处理,但这容易导致单次 GC 停顿变长;而追求低停顿,则需更频繁、更细粒度的回收(如分代收集、增量标记、并发清理),这会占用更多 CPU 资源,拖慢应用整体执行速度。
看业务类型决定优先级
吞吐量优先适合后台批处理、科学计算、ETL 任务等对响应延迟不敏感、但要求单位时间内完成尽可能多工作的场景。这类应用可接受秒级甚至更长的 STW(Stop-The-World)暂停,只要总运行时间短、CPU 利用率高。
低停顿时间则适用于交互式系统:Web API 服务、实时交易系统、游戏服务器、金融风控接口等。用户感知的是单次请求延迟,哪怕平均吞吐略低,也要避免因 GC 导致某次请求卡顿 200ms 以上。
选对收集器是基础前提
不同收集器在设计上就偏向不同目标:
- 吞吐量优先:Parallel Scavenge + Parallel Old(JDK 8 默认),通过多线程并行回收、自适应调优(-XX:+UseAdaptiveSizePolicy)最大化吞吐,但 STW 时间相对明显;
- 低停顿优先:G1(JDK 9+ 默认)、ZGC(JDK 11+)、Shenandoah(JDK 12+)。G1 用 Region 划分+预测停顿模型(-XX:MaxGCPauseMillis),可在可控停顿内完成大部分回收;ZGC/Shenandoah 支持并发标记与并发移动,STW 通常控制在 10ms 内,几乎不影响响应。
参数调优要围绕目标做取舍
即使选定收集器,仍需根据目标调整关键参数:
- 若追求吞吐量:适当增大堆(-Xmx)、提高新生代比例(-XX:NewRatio 或 -Xmn)、启用 GC 日志分析实际吞吐(-XX:+PrintGCDetails -Xloggc:gc.log),关注“GC time / total time”是否低于 5%;
- 若追求低停顿:限制最大停顿目标(如 G1 的 -XX:MaxGCPauseMillis=200)、预留足够内存避免退化为 Full GC、监控是否频繁触发 Mixed GC(说明老年代晋升过快,需调优 -XX:G1MixedGCCountTarget 或对象生命周期);
- 注意:盲目压缩停顿目标(如设 -XX:MaxGCPauseMillis=50)可能导致 GC 频次激增、CPU 占用飙升、吞吐骤降,反而得不偿失。
监控与验证比理论更重要
没有银弹参数,只有符合你真实负载的配置。上线前务必用生产流量或压测工具(如 JMeter、gatling)模拟真实对象分配速率、存活对象比例、请求分布特征。重点关注:
- GC 频次与单次耗时(jstat -gc 或 GC 日志);
- 应用 P99/P999 延迟曲线是否出现尖刺(对应 GC STW);
- CPU 使用率是否因 GC 线程持续高位(如 ZGC 并发阶段也会占 CPU);
- 内存是否稳定(避免因 Survivor 区过小导致提前晋升,加剧老年代压力)。
权衡不是非此即彼的选择题,而是结合业务 SLA、硬件资源、JVM 版本和实际负载持续迭代的过程。先明确“能接受的最长单次停顿是多少”和“每分钟至少要处理多少请求”,再选收集器、调参数、压测、观察、再调优。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











