Phaser 的核心是 register() 动态注册与 arriveAndAwaitAdvance() 步进分相协同形成的运行时协作机制,依赖线程主动声明参与和抵达来驱动流程,而非预设人数或固定轮次。
Phaser 的核心不是“多阶段”本身,而是
register() 动态注册
和
arriveAndAwaitAdvance() 步进分相
两者配合形成的运行时协作机制。它不靠预设人数,也不靠固定轮次,而靠每个线程“主动声明参与 + 主动宣告到达”来驱动整个流程。
register() 不是占位,是真实入场
调用
只是把内部计数器初始化为 5,并不代表有 5 个合法参与者。没调
就执行任何 arrive* 方法,必然抛
。
正确起点是
或
,从零开始
每个工作线程启动后、执行任务前第一件事:调
主线程若要参与(比如汇总结果),也得自己
;如果只协调不干活,就不注册,改用
等待
批量注册可用
,比循环
快一点,但它仍是“动作”,不是“上限声明”
arriveAndAwaitAdvance() 是阶段推进的触发点
这个方法干了三件事:抵达当前 phase、阻塞等待所有已注册且未注销的线程也抵达、等齐后自动进入下一 phase(phase 值 +1)。
它不是“单纯等待”,而是“到达 + 同步 + 推进”的原子组合
每次调用都对应一个明确的阶段边界,比如“数据加载完成”“校验通过”“聚合结束”
线程调用后,会一直阻塞到本阶段所有其他活跃参与者也都调用了该方法
返回值是推进后的 phase 编号,可用于后续判断或日志追踪
register() 和 arriveAndAwaitAdvance() 必须成对出现才有意义
单独注册不抵达,Phaser 不知道你是否准备好了;只抵达不注册,直接报错;注册后不抵达,phase 永远卡住。
典型安全模式:
→ 执行任务 →
→(可选)
不能省略
,也不能把它当成构造参数里的“默认配置”
如果某线程只参与部分阶段,就在退出时用
,而不是漏掉
主线程不用 arriveAndAwaitAdvance(),用 awaitAdvance(int) 更精准
主线程通常不干活,只观察节奏。它不需要“到达并等待”,而应等待子线程把某个 phase 走完,再触发下一阶段动作。
例如:等 phase 0 结束(全部数据加载完毕),再启动校验逻辑;等 phase 1 结束,再发起聚合
写法是:
,表示“阻塞直到 phase 0 完全结束、phase 1 已开启”
避免在主线程里调
,否则它会变成一个“必须参与的活跃方”,反而干扰调度逻辑
new Phaser(5)register()IllegalStateException: Not a registered partynew Phaser()new Phaser(null, 0)phaser.register()register()awaitAdvance(int)bulkRegister(n)register()register()arriveAndAwaitAdvance()arriveAndDeregister()register()arriveAndDeregister()arriveAndAwaitAdvance()phaser.awaitAdvance(0)arriveAndAwaitAdvance()