Phaser 是专为动态参与者数量和多阶段协同设计的同步工具,需显式注册参与者、原子退出、精准等待及嵌套分组。错误用法如 new Phaser(5) 或分开 arrive() 与 deregister() 会导致异常。

Phaser 是 Java 并发包中专为动态参与者数量 + 多阶段协同设计的同步工具,不是 CountDownLatch 的替代品,也不是 CyclicBarrier 的增强版——它解决的是“谁在哪个阶段参与、何时加入、何时退出”这个更细粒度的控制问题。
注册必须显式,不能靠构造参数“占位”
常见错误是写 new Phaser(5) 就以为已有 5 个合法参与者。其实这只是让内部计数器初始值为 5,不代表线程已注册。没调 register() 就直接 arrive() 或 arriveAndAwaitAdvance(),必抛 IllegalStateException: Not a registered party。
- 正确起点是
new Phaser()或new Phaser(null, 0),从零开始 - 每个工作线程启动后、执行任务前第一件事:调
phaser.register() - 主线程若只协调不干活,不用 register;若要参与(如汇总),也得自己
register() - 批量注册可用
bulkRegister(int),比循环register()略快,但它仍是动作,不是声明上限
退出必须原子,不能分两步写
线程完成某阶段后不再参与后续流程,必须用 arriveAndDeregister() 原子完成“到达 + 注销”。分开写 arrive() 和 deregister() 是错的——deregister() 根本不是 public 方法。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 预处理线程加载完数据 → 调
arriveAndDeregister(),立刻退出 - 汇总线程需等全部子任务结束 → 全程用
arriveAndAwaitAdvance()或配合awaitAdvance() - 主线程仅发号施令后退出 → 也要
arriveAndDeregister(),否则卡住 phase 推进
等待要精准,别盲目阻塞
awaitAdvance(int) 是最可控的等待方式:它只等指定 phase 结束,不关心当前有多少人注册。注意它不会自动 arrive(),调用者自己必须先 arrive() 或 arriveAndDeregister()。
立即学习“Java免费学习笔记(深入)”;
- 启动子任务前记下当前 phase:
int p0 = phaser.getPhase() - 分发完所有任务后调
phaser.awaitAdvance(p0),确保全部抵达第 0 阶段 - 再启动第 1 阶段逻辑(如校验),避免“部分还没开始,主线程已往下冲”
- 返回后 phase 可能已跳变,别缓存 phase 值做后续判断
分组协同用嵌套,别堆在一个 Phaser 下
当任务天然分组(如 4 组 worker 各自 map,再统一 reduce),平铺在一个 Phaser 下会导致语义混乱和竞争加剧。应使用嵌套 Phaser 实现分组与全局两级同步。
- 每组内部用一个子 Phaser,负责该组内线程的阶段对齐
- 主 Phaser 负责协调各组整体进度(例如等所有子组完成 map 后才进入 reduce)
- 子 Phaser 完成时,其父 Phaser 的对应线程调用
arrive(),表示该组就绪 - 避免单点瓶颈,提升并发吞吐与逻辑清晰度

















