Serial 与 Parallel 收集器

候选人小郑在面试拼多多 P6 时,面试官问道:

"Serial 和 Parallel 收集器有什么区别?"

小郑说:"Serial 单线程,Parallel 多线程..."面试官追问:"Parallel Scavenge 和 ParNew 有什么区别?"

小郑答不上来。面试官继续追问:"吞吐量优先的收集器是什么意思?"

小郑彻底卡住了...

一、核心问题:Serial 与 Parallel 收集器 🔴

1.1 问题拆解

第一层:四种收集器(有哪些?)
  "Serial、ParNew、Parallel Scavenge、Parallel Old 分别是做什么的?"
  考察点:年轻代 vs 老年代、单线程 vs 多线程

第二层:吞吐优先 vs 停顿优先(怎么区分?)
  "Parallel Scavenge 和 ParNew 的根本区别是什么?"
  考察点:吞吐量、GC 自适应调节

第三层:生产选型(怎么选?)
  "什么场景用什么收集器?"
  考察点:停顿时间 vs 吞吐量

1.2 ❌ 错误示范

候选人原话 A:"Serial 收集器已经没人用了。"

问题诊断:Serial 在客户端模式(-client)下仍然是默认选择。适合单核 CPU、堆较小的场景。还在嵌入式或简单后台服务中使用。

候选人原话 B:"ParNew 和 Parallel Scavenge 差不多。"

问题诊断:两者的根本区别在于目标——ParNew 追求停顿时间最短,Parallel Scavenge 追求吞吐量最高

1.3 标准回答

P5 级别:四种收集器

Serial(年轻代)

  • 单线程,年轻代收集器
  • 使用复制算法
  • Stop-The-World(STW)

Serial Old(老年代)

  • 单线程,老年代收集器
  • 使用标记-整理算法

ParNew(年轻代)

  • 多线程版本 Serial
  • 使用复制算法
  • CMS 收集器的年轻代收集器

Parallel Scavenge(年轻代)

  • 多线程,年轻代收集器
  • 使用复制算法
  • 目标是吞吐量优先

Parallel Old(老年代)

  • 多线程,老年代收集器
  • 使用标记-整理算法
  • 配合 Parallel Scavenge 使用

P6 级别:吞吐量优先

吞吐量的定义

吞吐量 = 运行用户代码时间 / (运行用户代码时间 + GC 花费时间)

吞吐量优先的收集器适用于后台计算任务——不在意停顿时间,更在意 CPU 的利用率。

Parallel Scavenge 的独特参数

# 最大 GC 停顿时间目标(软目标,不保证)
-XX:MaxGCPauseMillis=200  # 期望最大停顿时间 200ms

# 吞吐量目标
-XX:GCTimeRatio=19       # 目标吞吐量 = 19/(19+1) = 95%

# 开启自适应调节(GC Ergonomics)
-XX:+UseAdaptiveSizePolicy  # 默认开启

GC Ergonomics(自适应调节)

Parallel Scavenge 的核心优势是自适应调节

  • JVM 自动调整 Eden/Survivor 比例
  • 自动调整晋升阈值
  • 自动调整堆大小

不需要手动调优,只需设置吞吐量和停顿时间目标。

P7 级别:ParNew vs Parallel Scavenge

两者的核心区别

维度ParNewParallel Scavenge
目标最短停顿时间最大吞吐量
配合收集器配合 CMS 使用配合 Parallel Old 使用
自适应调节有(GC Ergonomics)
是否可与 CMS 配合✅ 可以❌ 不可以

【面试官心理】 这道题我能问到 P7 级别,是因为 Parallel Scavenge 的自适应调节是其独特优势。能说清 GC Ergonomics 原理的候选人说明他理解了 JVM 的自我调优能力。

1.4 追问升级

追问:Serial + Serial Old 和 Parallel Scavenge + Parallel Old 哪个更好?

取决于场景:

  • 桌面应用:Serial + Serial Old(停顿可以接受,CPU 资源有限)
  • 服务器应用:Parallel Scavenge + Parallel Old(吞吐量优先)

二、生产选型 🟡

2.1 选择策略

场景收集器理由
桌面应用、低延迟要求Serial + Serial Old简单,低开销
后台批处理、吞吐量优先Parallel Scavenge + Parallel Old吞吐量最高
Web 服务、响应时间优先ParNew + CMS / G1停顿时间可控

2.2 JVM 模式选择

# 64位 JVM 默认是 server 模式
# -server: Parallel Scavenge + Parallel Old
# -client: Serial + Serial Old

java -server MyApp  # 服务器模式(默认)
java -client MyApp # 客户端模式
💡

面试加分点:能说出"JDK 14 将 ParNew 和 Serial Old 的配置废弃(deprecated),推荐使用 G1",说明他关注了 JDK 新特性的演进。

⚠️

面试陷阱:被问到"Parallel Scavenge 的 MaxGCPauseMillis 设置越小越好吗",很多人会说"是"。准确答案是:不是。设置过小的停顿时间目标会导致频繁 GC(每次 GC 回收很少),反而降低吞吐量。MaxGCPauseMillis 是一个软目标,JVM 不保证严格满足。