phaser多阶段同步通过动态参与者管理与到达动作触发的隐式阶段推进实现精准调度。参与者需显式register()加入,用arrive()、arriveandawaitadvance()或arriveandderegister()触发phase递增,awaitadvance()需前置到达动作,主线程宜用awaitadvance()而非同步等待。

Phaser 多阶段同步不是简单地“等齐再走”,而是靠动态参与者管理 + 阶段隐式推进的组合机制实现精准调度。它不预设线程数,也不强制所有线程全程参与,真正适配真实业务中任务规模浮动、角色分工不同的场景。
阶段推进不是自动发生的,而是由“到达动作”触发
Phaser 的 phase 号不会凭空递增。只有当一个已注册的参与者调用 arrive()、arriveAndAwaitAdvance() 或 arriveAndDeregister() 时,内部计数器才会响应——未到达的线程不会推动阶段前进。
- 每个 arriveAndAwaitAdvance() 调用既表示“我到了”,也隐含“我要等别人”,成功返回时 phase 已+1
- arrive() 只完成“到达”,不等待;若需后续等待,必须搭配 awaitAdvance(int)
- awaitAdvance(int phase) 是非阻塞等待的起点:调用前必须先 arrive() 或 arriveAndDeregister(),否则会永远卡住
动态注册必须显式执行,不能靠构造参数“占位”
写 new Phaser(5) 并不等于有 5 个合法参与者,只是把内部计数器初始化为 5。没有线程调用 register(),就没人真正加入同步流程。
- 推荐从零开始:new Phaser() 或 new Phaser(null, 0)
- 每个工作线程启动后、执行任务前第一件事就是 phaser.register()
- 主线程若要参与(如汇总结果),也得自己 register();若只协调不干活,就别注册,改用 awaitAdvance(int) 观察节奏
- 批量注册可用 bulkRegister(n),比循环调 register() 略快,但它仍是运行时动作,不是声明上限
阶段性退出必须原子完成,不能拆成两步
线程完成某阶段后不再参与后续流程,必须用 arriveAndDeregister() 一次性完成“到达 + 注销”。分写 arrive() 和所谓 deregister() 是错的——后者根本不是 public 方法。
- 预处理线程加载完数据 → 立即调 arriveAndDeregister(),干净退出
- 汇总线程需等全部子任务结束 → 全程用 arriveAndAwaitAdvance() 或配合 awaitAdvance()
- 主线程仅发号施令后退出 → 同样要 arriveAndDeregister(),否则 phase 卡住不推进
- 错误模式:arriveAndAwaitAdvance() 后再调 arriveAndDeregister() —— 前者已推进 phase,后者可能落在新 phase,导致计数错乱
主线程应做节奏控制器,而非盲目同步者
主线程不干活,只控制流程边界,就不该和工作线程一样调 arriveAndAwaitAdvance()。它该用 awaitAdvance(int) 精准等待某个 phase 结束。
- 启动子任务前记下当前 phase:int p0 = phaser.getPhase()
- 分发完所有任务后调 phaser.awaitAdvance(p0),确保全部抵达第 0 阶段
- 再启动第 1 阶段逻辑(如校验),避免“部分还没开始,主线程已往下冲”
- awaitAdvance() 不自动 arrive(),调用者自己必须先完成到达动作
- 返回后 phase 可能已跳变,别缓存 phase 值做后续判断











