ParNew 回收器
ParNew:Serial 的多线程版本
ParNew 是年轻代收集器,本质上是多线程版本的 Serial——使用复制算法,但用多个线程并行执行垃圾回收。
ParNew 的工作原理
Serial(单线程): ───▶ Eden ──▶ [线程1 标记] ──▶ [线程1 复制] ──▶ 完成
↑
│ 停顿时间 = T
ParNew(多线程): ───▶ Eden ──▶ [线程1+2+3+4 并行] ──▶ 完成
↑
│ 停顿时间 ≈ T / N(N = 线程数)与 Serial 的对比
| 维度 | Serial | ParNew |
|---|---|---|
| 算法 | 复制 | 复制 |
| 线程数 | 单线程 | 多线程(-XX:ParallelGCThreads 控制) |
| 停顿时间 | 长 | 短(N 倍加速) |
| 吞吐量 | 低 | 高 |
| 使用场景 | 低配机器 | Web 服务(CMS 的年轻代) |
ParNew 的使用
bash
# ParNew 只能与 CMS 组合使用
java -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MyApp
# 设置并行线程数(默认 = CPU 核心数)
java -XX:+UseParNewGC -XX:ParallelGCThreads=4 MyApp为什么 ParNew 只能配 CMS
ParNew 专门为 CMS 设计,它和 CMS 的交互非常紧密:
ParNew 年轻代 + CMS 老年代:
┌─────────────────────────────────────────────────┐
│ 年轻代 │
│ ┌──────────────────────────────────────────┐ │
│ │ ParNew(多线程复制算法) │ │
│ │ 线程数:ParallelGCThreads(默认 = CPU 核数)│ │
│ └──────────────────────────────────────────┘ │
│ │ 晋升 │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ CMS(并发标记清除) │ │
│ │ 老年代收集:大部分与用户线程并发 │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘ParNew 不能与 Throughput GC(Parallel Old)组合——如果需要多线程年轻代 + 多线程老年代,直接用 Throughput GC(ParallelGC)。
ParNew 的 GC 日志
bash
java -XX:+UseParNewGC \
-XX:+UseConcMarkSweepGC \
-XX:+PrintGCDetails \
MyApp日志示例:
# ParNew MinorGC(多线程)
2026-03-22T10:00:00.123+0800: [GC (Allocation Failure)
[ParNew: 20480K->2048K(22528K), 0.0084567 secs]
20480K->2048K(22528K), 0.0085678 secs]
[Times: user=0.03 sys=0.01, real=0.01 secs]
# ↑
# 并行 GC 线程的 user 时间累加 > real 时间日志解读:
ParNew:年轻代多线程收集器user=0.03:N个线程的 CPU 时间累加real=0.01:实际墙钟时间(≈ user / N)
ParNew 的参数配置
bash
# 设置年轻代大小(影响 MinorGC 频率)
java -Xmn512m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MyApp
# 设置 Survivor 比例
java -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MyApp
# 设置并行线程数
java -XX:ParallelGCThreads=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC MyApp
# 建议:ParallelGCThreads 不超过 8 个
# 超过 8 个后,线程切换开销可能超过并行收益ParNew 的优势
1. 停顿时间更短
java
// 场景:年轻代 512MB,单线程 Serial 需要 100ms
// 8 线程 ParNew 只需要约 15ms
// 停顿时间大幅缩短2. 与 CMS 完美配合
CMS 并发阶段 ──▶ ParNew MinorGC ──▶ CMS 并发阶段
│ │
│ 交替执行 │ 最短停顿
│ │
CMS 大部分时间并发,ParNew 停顿时间很短3. 自适应调节
ParNew 可以和 CMS 共享自适应调节参数:
bash
# 自适应调节年轻代大小
java -XX:+UseAdaptiveSizePolicy \
-XX:+UseParNewGC \
-XX:+UseConcMarkSweepGC \
MyAppParNew 的局限性
| 局限性 | 说明 |
|---|---|
| 只能配 CMS | 不能与 Parallel Old 组合 |
| CPU 密集 | GC 时消耗所有 CPU 核心 |
| 吞吐量不如 Throughput | Throughput GC 专门优化吞吐量 |
| JDK 14 已废弃 | 不再推荐使用 |
JDK 14 之后:ParNew 的替代
JDK 14 移除了 -XX:+UseParNewGC 选项(CMS 本身也在 JDK 14 中移除)。推荐替代方案:
bash
# 推荐使用 G1(可预测停顿)
java -XX:+UseG1GC MyApp
# 或者 ZGC(超低延迟)
java -XX:+UseZGC MyAppParNew vs Throughput 的选择
| 场景 | 选择 | 原因 |
|---|---|---|
| 低延迟 Web 服务 | G1 | CMS 已废弃,G1 是官方推荐 |
| 高吞吐批处理 | Throughput GC | 专门优化吞吐量 |
| CMS 迁移 | G1 | G1 可以替代 CMS |
| 新项目 | G1 / ZGC | 不再推荐 ParNew |
本节小结
ParNew 收集器的核心要点:
| 维度 | 说明 |
|---|---|
| 本质 | 多线程版本的 Serial(年轻代) |
| 算法 | 复制算法 |
| 线程数 | 多线程并行(ParallelGCThreads) |
| 搭档 | CMS 老年代(唯一组合) |
| JDK 状态 | JDK 14 移除 |
| 替代方案 | G1 / ZGC |
ParNew 作为 CMS 的年轻代收集器,曾经是低延迟 Web 服务的主流选择。但随着 CMS 的废弃和 G1 的成熟,ParNew 也逐渐退出了历史舞台。
下一节,我们来看 Parallel/Parallel Old 回收器。
