phaser的核心职责是协调线程在各阶段的到达与同步节奏,而非任务调度;需显式register()注册参与者,用arriveandderegister()原子退出,主线程应调awaitadvance(int)精准等待,分组协同推荐嵌套phaser。

Phaser 不是“多阶段调度器”,它不负责分配任务、决定执行顺序或管理线程池。它的核心职责是协调已启动线程在各阶段的到达与同步节奏,靠参与者动态注册 + 阶段隐式推进来适配真实并发场景——任务数不确定、角色不一致、退出时机各异。
动态注册必须显式,不能靠构造参数“占位”
写 new Phaser(5) 并不等于有 5 个合法参与者。这只是让内部计数器初始为 5,不代表任何线程真正注册。没调 register() 就直接 arrive(),会抛 IllegalStateException: Not a registered party。
- 正确起点是
new Phaser()或new Phaser(null, 0),从零开始 - 每个工作线程启动后、执行任务前第一件事:调
phaser.register() - 主线程若要参与同步(比如汇总结果),也得自己
register();若只协调不干活,就别注册,改用awaitAdvance(int)等待 - 批量注册可用
bulkRegister(int),比循环register()略快,但它仍是动作,不是声明上限
阶段性退出必须原子,不能拆成两步
线程完成某阶段后不再参与后续流程,必须用 arriveAndDeregister() 原子完成“到达 + 注销”。deregister() 根本不是 public 方法,分写 arrive() 和 deregister() 是错的。
- 预处理线程加载完数据 → 调
arriveAndDeregister(),立刻退出 - 汇总线程需等全部子任务结束 → 全程用
arriveAndAwaitAdvance()或配合awaitAdvance() - 主线程仅发号施令后退出 → 也要
arriveAndDeregister(),否则卡住 phase 推进 - 错误模式:
arriveAndAwaitAdvance()后再调arriveAndDeregister()—— 前者已阻塞并推进 phase,后者可能落在新 phase,导致计数错乱
阶段推进靠 awaitAdvance(int),不是盲目等待
主线程不干活,只观察节奏。它不该调 arriveAndAwaitAdvance(),而应调 awaitAdvance(int phase) 精准等待某阶段结束。
- 启动子任务前记下当前 phase:
int p0 = phaser.getPhase() - 分发完所有任务后调
phaser.awaitAdvance(p0),确保全部抵达第 0 阶段 - 再启动第 1 阶段逻辑(如校验),避免“部分还没开始,主线程已往下冲”
-
awaitAdvance()不自动arrive(),调用者自己必须先arrive()或arriveAndDeregister() - 返回后 phase 可能已跳变,别缓存 phase 值做后续判断
分组协同用嵌套 Phaser,避免单点瓶颈
当任务天然分组(如多个 worker 组各自同步,再由组长统一协调),可让子 Phaser 注册到父 Phaser,形成树状协同:
- 创建父 Phaser:
Phaser root = new Phaser(); - 每组启动时新建子 Phaser:
Phaser group = new Phaser(root);—— 构造时传入 parent,子 phaser 完成其 own phase 时会自动为 parentarrive() - 这样,父 phaser 的阶段推进代表“所有子组均已抵达当前阶段”,天然支持 Map-Reduce 类模式











