Phaser 的设计核心是按需协作的阶段化同步:阶段号单调递增,由 arriveAndAwaitAdvance() 自然驱动;参与者须显式注册与注销;支持父子层级解耦协同;onAdvance 可定制阶段流转逻辑。

Java 中 Phaser 的设计思路不是把线程“绑死”在固定节奏里,而是让每个任务按需加入、阶段抵达、适时退出,形成一种可伸缩、可观察、可终止的协同流。
以阶段为单位推进,而非靠计数器倒数
Phaser 的 phase 从 0 开始单调递增,每次推进只发生在所有当前注册参与者都完成本阶段后。它不依赖定时器、不靠外部触发,而是由 arriveAndAwaitAdvance() 这类到达动作自然驱动。一个线程调用它,既表示“我完成了”,也隐含“我要等别人”。返回值是下一阶段号,可直接用于分支判断,比如:
- phase == 1 时做资源预检,失败则调用 forceTermination()
- phase == 2 后根据 getArrivedParties() 判断是否过半,决定是否提前汇总
- 阶段编号是只读状态快照,不是执行轮次,也不保存业务数据
参与者必须运行时显式管理
new Phaser(5) 只初始化内部计数器,并不代表已有 5 个合法参与者。真实协作中,线程应在就绪后主动调用 register() 加入;完成某阶段后不再参与后续流程,必须用 arriveAndDeregister() 原子注销。常见错误包括:
- 未 register 就调 arrive 系列方法 → 抛 IllegalStateException: Not a registered party
- 分开写 arrive() 和 deregister() → 后者根本不是 public 方法
- 主线程只发号施令却不注册,又不调 awaitAdvance() → 导致阶段卡住
分层结构解耦组内协同与组间对齐
当任务天然分组(如多个区域并行处理、多组 worker 各自 map),平铺在一个 Phaser 下会导致语义模糊和 CAS 竞争加剧。此时应构建父子层级:
立即学习“Java免费学习笔记(深入)”;
- 顶层 Phaser root 作为总控,只感知子组“是否就绪”
- 每个子组新建 Phaser group = new Phaser(root),内部自行管理阶段
- 子组完成本阶段后自动为父 Phaser 调用 arrive(),无需手动上报
- 主线程调用 root.awaitAdvance(2) 即可等待所有子组统一进入第 2 阶段
onAdvance 定制阶段流转逻辑
默认阶段推进是机械的,但业务常需决策能力。onAdvance(int phase, int registeredParties) 是阶段切换前的统一入口,可用于:
- 校验中间结果:若 phase == 2 时汇总失败,返回 true 终止整个流程
- 上报指标或清理资源:返回 false 继续推进,同时做日志、释放句柄等
- 动态调整后续参与者数:registeredParties 参数反映下一阶段预计人数,可用于弹性扩缩


















