Phaser专为单JVM内多线程多阶段动态协同设计,阶段推进靠arriveAndAwaitAdvance()实现齐步走,参与者需显式register()和arriveAndDeregister()管理,onAdvance()控制流程,复杂场景推荐父子Phaser分层协同。

Phaser不是用来替代分布式锁或跨节点协调的工具,它专为单JVM内、多线程、多阶段、动态参与者数量的任务协同而设计。核心在于把“阶段推进”和“参与者管理”解耦——阶段靠到达行为自然演进,人数靠运行时注册/注销实时调整,两者互不绑定,才能支撑真实业务中的弹性伸缩。
阶段推进必须由 arriveAndAwaitAdvance() 驱动
仅调用 arrive() 只是上报完成,不会阻塞等待;真正实现“齐步走”的,是 arriveAndAwaitAdvance()。它做两件事:标记本线程已到达当前阶段,并阻塞直到所有当前注册参与者都调用该方法,然后 phase 自动 +1,线程被唤醒进入下一阶段。
- 阶段编号从 0 开始,首次调用后进入 phase 1,第二次进入 phase 2,依此类推
- 返回值是下一阶段编号,可用于分支判断,例如 if (phaser.arriveAndAwaitAdvance() == 2) { /* 第三阶段逻辑 */ }
- 未 register 就调用该方法,会抛 IllegalStateException:Not a registered party
参与者管理必须显式且原子
new Phaser(5) 不等于已有 5 个合法参与者,那只初始化内部计数器,不代表线程已注册。所有工作线程启动后、执行任务前,第一件事必须是调用 register()。
- 新线程加入:调用 register() 或 bulkRegister(n),立即成为当前及后续阶段的参与者
- 阶段性退出:必须用 arriveAndDeregister(),它原子完成“到达+注销”,避免分两步写导致状态错乱
- 主线程若参与协调(如汇总),也需 register();若只监听,就用 awaitAdvance(int) 等待指定阶段结束
- Phaser 不泄漏——任务实例结束、所有线程注销后,对象可被 GC 回收
阶段流转控制靠 onAdvance() 插入业务逻辑
onAdvance(int phase, int registeredParties) 是阶段切换前的统一入口,它在所有线程完成当前 phase、准备推进前被自动调用,是控制流程走向的关键点。
- 返回 false(默认):继续进入下一阶段
- 返回 true:终止 Phaser,后续 arrive 调用立即失败,适合任务自然完结或异常熔断
- 常用于日志打点、中间结果校验、资源清理,例如:if (phase == 1 && hasError()) return true;
- 参数 registeredParties 是下一阶段预计参与数,可用于判断是否还有活跃任务
复杂任务推荐父子 Phaser 分层协同
当任务天然分组(如多个 worker 组并行 map,再统一 reduce),平铺在一个 Phaser 下会导致阶段语义模糊、推进节奏失真。应采用父子结构,让同步粒度与业务结构对齐。
- 父 Phaser 控制整体流程节奏,例如等待所有子组完成 map 后才触发 reduce
- 每个子组创建独立子 Phaser,并在构造时传入父 Phaser:new Phaser(parent)
- 子 Phaser 推进自身 phase 时,会自动为父 Phaser 执行一次 arrive(),形成级联推进
- 避免在单一 Phaser 内混杂不同职责的线程,降低调试与维护成本

















