Phaser本质是可编程阶段状态机,依赖注册参与者与阶段推进规则驱动;关键在注册/退出匹配生命周期、同步动作绑定阶段末尾、onAdvance精准干预阶段切换。

Phaser 本质是一个可编程的阶段状态机,它不靠预设人数或固定轮次驱动,而是用“当前注册参与者 + 阶段推进规则”共同决定何时同步、何时流转。用好它,关键在三点:注册与退出必须匹配业务生命周期,同步动作要绑定到阶段末尾,阶段切换逻辑得靠 onAdvance 精准干预。
阶段划分要贴合实际任务流
别把 Phaser 当成通用屏障硬套流程。先拆解任务本身有没有天然阶段边界——比如“加载配置→拉取分片数据→本地聚合→提交结果”,每个箭头就是一次 phase 推进点。阶段数不是越多越好,而是每个阶段要有明确的完成标志和共享依赖:
- 阶段 0(初始化):所有线程加载元数据、校验权限,完成后才能进入数据读取
- 阶段 1(执行):各线程处理各自分片,但彼此不依赖,可并行
- 阶段 2(收口):必须等全部分片就绪,才触发汇总与落库
阶段之间有数据或状态依赖,才是引入 Phaser 的合理理由;否则单个 CountDownLatch 就够了。
注册与注销必须原子且及时
注册不是“声明我要来”,而是“我现在就参与”。new Phaser(5) 不等于已有 5 个合法参与者,只是计数器初始为 5,没 register 就调 arrive 会直接抛异常。同样,注销不是“我干完了”,而是“我不再影响下一阶段”:
- 工作线程启动后第一件事:phaser.register()
- 完成某阶段且不再参与后续:必须用 arriveAndDeregister(),不能分开写 arrive() + deregister()
- 主线程若只协调不干活,不注册;若要等某个阶段结束再发指令,就得自己 register 后再 awaitAdvance()
漏注册、晚注销,都会导致其他线程在某 phase 卡住,因为 Phaser 只等“当前已注册且未注销”的人。
同步动作要选对方法,别混用
arrive() 是通知,不阻塞;arriveAndAwaitAdvance() 是到达+等待,是阶段同步的核心;awaitAdvance(int phase) 是纯等待,适合主线程监听,但它不自动 arrive,调用前必须确保自己已注册并完成当前工作:
- 工作线程每个阶段结尾统一用 arriveAndAwaitAdvance(),返回值是下一 phase 编号,可用于 if (phase == 2) 做特殊处理
- 主线程想等所有 worker 进入阶段 1,可先记下 phaser.getPhase(),再分发任务,最后调 phaser.awaitAdvance(p0)
- 绝对不要在没 arrive 的情况下调 awaitAdvance,否则永远等不到 phase 变化
onAdvance 是状态流转的控制开关
这个方法在所有线程都完成当前 phase、Phaser 准备推进前被调用,参数 phase 是刚结束的阶段号(从 0 开始),registeredParties 是下一阶段预计参与数。它不是日志钩子,而是真正的决策点:
- 返回 false(默认):继续推进到下一 phase
- 返回 true:终止 Phaser,后续所有 arrive 类方法立即返回负值,适合任务自然结束或异常熔断
- 常见用法:phase == 2 && registeredParties == 0 时 return true;或检查中间结果失败时提前终止
别把它当成回调随便打日志,它的返回值直接决定整个同步流程是否继续。

















