Phaser 是专为动态参与者数量和角色的并发场景设计的同步工具,核心在于显式注册、原子注销、精准阶段等待及嵌套分组协同。

Phaser 不是“移相器”,也不是固定人数的阶段同步器。它专为参与者数量不确定、各阶段参与角色不一致的并发场景而生——关键在动态注册、按需退出、阶段精准等待。
注册必须显式,不能靠构造参数“占位”
new Phaser(5) 只是让内部计数器起始为 5,并不代表已有 5 个合法参与者。没调 register() 就直接 arrive(),必抛 IllegalStateException: Not a registered party。
- 正确起点是 new Phaser() 或 new Phaser(null, 0),从零开始
- 每个工作线程启动后、执行任务前第一件事:调 phaser.register()
- 主线程若只协调不干活,不用 register;若要参与同步(如汇总),也得自己 register()
- 批量注册可用 bulkRegister(int),比循环 register() 略快,但它仍是动作,不是声明上限
退出要用 arriveAndDeregister(),不是两步操作
线程完成某阶段后不再参与后续流程,必须用 arriveAndDeregister() 原子完成“到达 + 注销”。分写 arrive() 和 deregister() 是错的——deregister() 根本不是 public 方法。
- 预处理线程加载完数据 → 调 arriveAndDeregister(),立刻退出
- 汇总线程需等全部子任务结束 → 全程用 arriveAndAwaitAdvance() 或配合 awaitAdvance()
- 主线程仅发号施令后退出 → 也要 arriveAndDeregister(),否则卡住 phase 推进
- 高频小任务频繁注册/注销会触发内部数组重分配,微秒级任务建议改用 CompletableFuture 链式编排
阶段推进靠 awaitAdvance(int),不是盲目 await
主线程不干活,只观察节奏。它不该调 arriveAndAwaitAdvance(),而应调 awaitAdvance(int phase) 精准等待某阶段结束。
- 启动子任务前记下当前 phase:int p0 = phaser.getPhase()
- 分发完所有任务后调 phaser.awaitAdvance(p0),确保全部抵达第 0 阶段
- 再启动第 1 阶段逻辑(如校验),避免“部分还没开始,主线程已往下冲”
- 注意:awaitAdvance() 不自动 arrive(),调用者自己必须先 arrive() 或 arriveAndDeregister()
- 返回后 phase 可能已跳变,别缓存 phase 值做后续判断
分组协同用嵌套 Phaser,避免单点瓶颈
当任务天然分组(如 4 组 worker 各自 map,再统一 reduce),平铺在一个 Phaser 下会导致语义混乱和竞争加剧。
- 创建父 Phaser:Phaser root = new Phaser()
- 每组新建子 Phaser:Phaser group = new Phaser(root)(构造时传 parent)
- 子 phaser 推进 own phase 时,自动为 parent.arrive()
- 父 phaser 的 phase 推进,代表“所有子组均已抵达当前阶段”,天然支持 Map-Reduce 流水线










