phaser阶段推进由参与者到达动作驱动而非静态屏障:所有已注册未注销线程调用arrive/arriveandawaitadvance/arriveandderegister任一方法后,phase才+1;new phaser(3)仅初始化registeredparties为3,实际参与数取决于运行时register/deregister状态。

Phaser同步不是靠“等齐再放行”的静态屏障,而是由参与者行为驱动的阶段演进过程:每个线程完成当前阶段后调用 arriveAndAwaitAdvance(),触发隐式推进;所有已注册且未注销的线程都完成该动作,phase 才从 0 开始递增,新阶段立即开始。
阶段推进靠到达动作,不是靠计时或调度
Phaser 不会自动推进阶段,phase 号也不会随时间增长。它只在满足一个条件时才 +1:当前已注册的参与者全部调用了 arrive、arriveAndAwaitAdvance 或 arriveAndDeregister 中的任意一种到达操作。其中:
- arriveAndAwaitAdvance() 是最常用方式——既标记到达,又阻塞等待全体就绪,返回值就是新 phase 编号
- arrive() 仅上报完成,不等待;若后续需同步,必须再调 awaitAdvance(int)(且前提是已 arrive)
- arriveAndDeregister() 一次性完成“到达 + 退出”,该线程不再参与下一阶段
参与者数量是动态快照,不是初始配置
new Phaser(3) 并不等于“绑定了 3 个线程”,只是把内部 registeredParties 初始化为 3。真正决定某阶段能否结束的,是调用 arriveAndAwaitAdvance() 前一刻“已 register 且未 deregister”的线程数。
- 新线程启动后第一件事应是 phaser.register(),否则它的完成不会被计入当前阶段
- 批量加入可用 bulkRegister(n),比循环 register() 更高效,但仍属运行时行为
- 线程中途退出必须用 arriveAndDeregister(),不能拆成 arrive() + “伪注销”(后者不存在)
阶段切换可插入业务逻辑,靠 onAdvance 钩子
重写 onAdvance(int phase, int registeredParties) 方法,就能在每个阶段刚结束、新阶段尚未开始时执行自定义动作:
- 参数 phase 是刚刚完成的阶段号(如 phase=1 表示第二阶段刚结束)
- 参数 registeredParties 是下一阶段预计参与数(含新注册但尚未到达的线程)
- 返回 false:正常进入下一阶段(默认)
- 返回 true:终止 Phaser,后续 arrive 类调用立即返回,适合熔断或自然收尾
主线程宜做协调者,而非盲目同步者
主线程不必和工作线程一样全程参与计算。常见合理用法包括:
- 构造时 new Phaser(1),自己先注册,再启动子线程并让它们 register()
- 关键节点调用 awaitAdvance(phaser.getPhase()),监听阶段变化而不阻塞执行
- 异常时调用 forceTermination() 快速中断整个流程
- 仅发号施令后退出,则用 arriveAndDeregister() 干净离场,避免卡住 phase











