1. CountDownLatch(倒计时门闩)
工作原理:
CountDownLatch
就像一个“倒计时的门闩”。它允许一个或多个线程等待,直到其他线程完成某些任务后再继续执行。
- 门闩的初始计数:比如说,你设置了一个初始计数值(
count
),表示有几个任务需要完成。 - 任务完成后倒计时:每当一个任务完成,就通过
countDown()
方法将计数减1。 - 所有任务完成后开闸:当计数减到0时,门闩打开,所有等待的线程就可以继续执行了。
场景举例:
假设你是一个班主任,带着学生去春游。为了出发前确保每个人都准备好,你可以:
- 给每个学生分配任务,比如“带水”、“带食物”、“带地图”。
- 你设置一个门闩,计数为3(因为有3个任务)。
- 你自己在门闩前等待,直到所有人都完成任务。
- 每个学生完成任务后,通知你“我准备好了”(调用
countDown()
)。 - 当计数减到0时,表示所有任务都完成,你们就可以出发了。
适用场景:
- 等待一组任务完成后再继续执行,比如:
- 主线程等待一批子线程执行完毕。
- 启动服务时,确保所有依赖的模块加载完毕后再启动主服务。
2. Phaser(阶段器)
工作原理:
Phaser
更像一个“多阶段的闸门”,适合处理多阶段任务。它允许线程在每个“阶段”上同步,并且支持动态注册和注销参与者。
- 阶段的概念:
Phaser
将任务分成多个阶段,每个阶段都需要一组线程完成后才能进入下一阶段。 - 动态参与者:与
CountDownLatch
不同,Phaser
可以动态增加或减少参与的线程(或称为“参与方”)。 - 阶段完成的信号:线程在完成当前阶段后,通过调用
arriveAndAwaitAdvance()
方法告诉Phaser
“我完成了这个阶段,我在等其他人”。
场景举例:
假设你组织了一场接力赛跑,每组选手需要跑完“起点到中点”和“中点到终点”两个阶段:
- 你可以用
Phaser
来管理每个阶段的同步。 - 所有的选手在起点,等待比赛开始(第一阶段)。
- 每个选手跑到中点后,等待其他选手到达中点(第二阶段)。
- 所有选手到达中点后,比赛继续,跑向终点(第三阶段)。
- 如果某些选手中途退出(比如受伤),
Phaser
也能动态减少参与者。
适用场景:
- 多阶段任务的同步,比如:
- 一个复杂的计算任务分为多个步骤,每一步都需要所有线程完成后才能进入下一步。
- 动态的参与者加入或退出任务的情况。
3. 区别总结
特性 | CountDownLatch | Phaser |
---|---|---|
是否多阶段 | 只能控制一次(单阶段) | 可以控制多阶段 |
是否动态参与 | 不支持,线程数固定 | 支持动态注册和注销线程 |
是否重用 | 不能重用,倒计时用完就失效 | 可以重用,每个阶段都会自动重置 |
复杂性 | 简单,适合固定数量的线程 | 复杂,适合多阶段任务和动态线程场景 |
4. 总结使用场景
-
用
CountDownLatch
:- 适合单次的、固定数量的任务同步。
- 比如,主线程等待多个子线程完成工作。
-
用
Phaser
:- 适合多阶段任务,或者线程数量可能动态变化的场景。
- 比如,多阶段的并发计算任务,或者线程在不同阶段加入和退出。
