Phaser实现多阶段同步的关键在于分离线程参与权与阶段推进机制:线程可动态register/arriveAndDeregister,阶段由存活参与者共同驱动递增,支持主线程协调、树形分组及阶段钩子扩展。

Phaser 实现多阶段同步的关键,不是“比 CyclicBarrier 多几个阶段”,而是把线程的“是否参与”和“阶段是否推进”彻底分开——线程可以随时加入或退出,而阶段仍能稳定递进。
动态注册与注销决定谁在哪个阶段等待
每个线程必须显式调用 register() 才被计入当前阶段计数;完成任务后调用 arriveAndDeregister() 就永久退出后续所有阶段。这和 CyclicBarrier 构造时就锁死 parties(不可变)有本质区别。
- 新线程启动后第一行应是
phaser.register(),否则后续arriveAndAwaitAdvance()会抛IllegalStateException: Not registered - 某 worker 只参与前两阶段?第二阶段末尾调一次
arriveAndDeregister(),它对 phase=2 之后完全隐身 - 刚注册就想立刻参与当前阶段?需紧接着调
arriveAndAwaitAdvance()对齐,否则默认从下一阶段开始同步 - 批量拉起子任务时,用
bulkRegister(n)比循环register()更高效,但它仍是运行时动作,不是预设上限
主线程可做纯协调者,不参与计算
CyclicBarrier 要求所有线程平等阻塞,谁先到谁等;Phaser 允许主线程以“非参与者”身份存在,仅靠 awaitAdvance(int phase) 等待特定阶段结束。
- 例如:等 phase=0(数据加载)全部完成,再触发 phase=1(校验逻辑),主线程无需注册、不消耗计算资源
- 业务逻辑更清晰:工作线程按需进出,主线程专注流程编排和触发时机
- 避免把协调逻辑硬塞进工作线程,减少职责混杂
天然支持树形分组,应对嵌套同步需求
当任务天然分组(如 4 组并行 map 后统一 reduce),CyclicBarrier 只能退化为多个独立实例;Phaser 可通过父子嵌套实现层级协同。
立即学习“Java免费学习笔记(深入)”;
- 子组创建时传入父 Phaser:
new Phaser(parent) - 子组完成自己的阶段,会自动为父 Phaser 调一次
arrive() - 父 Phaser 的 phase 推进,代表“所有子组均已抵达当前阶段”
- 这种结构减少高并发下的竞争,提升扩展性,也更贴近真实业务分层
阶段推进由参与者行为驱动,而非预设节奏
Phaser 的 phase 是单调递增整数,初始为 0;每当所有当前已注册且未注销的线程都完成抵达操作,phase 自动 +1。这个推进是原子的、不可跳过、也不可由单个线程主动触发。
-
getPhase()可实时获取当前阶段号,用于日志、条件分支或监控埋点 - 重写
onAdvance(int phase, int registeredParties)可在阶段切换时做清理、校验或终止判断(返回 true 表示终止同步) - 不能靠“跳过 await”来退出同步——未调
arrive*的线程不会被计入计数,会导致其他线程永远阻塞



















