CountDownLatch、CyclicBarrier、Semaphore
三者都是 java.util.concurrent 包下的并发协调工具,用于控制多线程执行顺序。
CountDownLatch(倒计时锁)
作用
- 一等多:一个线程等待其他多个线程完成
- 计数器递减,归零时触发
使用示例
Java
// 主线程等待3个工作线程完成
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
// 执行任务
latch.countDown(); // 计数减1
}).start();
}
latch.await(); // 主线程等待,计数归零后继续
System.out.println("所有工作线程完成");
特点
- 计数器只能递减,不可重置
- 一次性使用,计数归零后无法复用
- await() 可设置超时:
latch.await(5, TimeUnit.SECONDS)
适用场景
- 主线程等待多个子任务完成
- 服务启动等待多个组件就绪
CyclicBarrier(循环屏障)
作用
- 多等多:多个线程互相等待,都到达屏障点后一起继续
- 可循环使用
使用示例
Java
// 3个线程互相等待,都到达后一起继续
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程到达屏障,执行汇总");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
// 第一阶段工作
barrier.await(); // 等待其他线程
// 第二阶段工作(所有线程都到达后一起执行)
}).start();
}
特点
- 计数器可重置,循环使用
- 可指定屏障动作:所有线程到达后执行回调
- await() 可设置超时
适用场景
- 多线程分阶段并行计算
- 多线程定时汇总
Semaphore(信号量)
作用
- 控制同时访问资源的线程数量
- 可用于限流
使用示例
Java
// 允许3个线程同时访问
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可(最多3个同时持有)
// 访问受限资源
} finally {
semaphore.release(); // 释放许可
}
}).start();
}
特点
- 可设置公平/非公平:
new Semaphore(3, true)为公平模式 - acquire() 可设置超时:
semaphore.tryAcquire(3, TimeUnit.SECONDS) - 可动态调整许可数量
适用场景
- 限流:控制并发访问数量
- 资源池:如数据库连接池控制
三者对比
| 特性 | CountDownLatch | CyclicBarrier | Semaphore |
|---|---|---|---|
| 作用 | 一等多 | 多等多 | 控制并发数 |
| 计数方向 | 递减 | 递增到阈值 | 不计数 |
| 是否可重用 | ❌ 一次性 | ✅ 可循环 | ✅ 可复用 |
| 等待触发 | 计数归零 | 达到指定数量 | 获取许可 |
| 适用场景 | 等待子任务完成 | 分阶段协作 | 并发限流 |
典型场景示例
CountDownLatch:等待所有任务完成
Java
CountDownLatch latch = new CountDownLatch(5);
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
try {
// 处理任务
} finally {
latch.countDown();
}
});
}
latch.await();
executor.shutdown();
CyclicBarrier:分阶段并行处理
Java
CyclicBarrier barrier = new CyclicBarrier(10);
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executor.submit(() -> {
phase1();
barrier.await(); // 等待所有线程完成阶段1
phase2();
barrier.await(); // 等待所有线程完成阶段2
});
}
Semaphore:数据库连接限流
Java
Semaphore semaphore = new Semaphore(10); // 最多10个并发
public Connection getConnection() throws InterruptedException {
semaphore.acquire();
return connectionPool.borrowConnection();
}
public void releaseConnection(Connection conn) {
connectionPool.returnConnection(conn);
semaphore.release();
}
要点总结
- CountDownLatch:一等多,计数递减,一次性,适合等待子任务完成
- CyclicBarrier:多等多,可循环,适合分阶段协作
- Semaphore:控制并发数量,可复用,适合限流
- CountDownLatch 计数归零后不可复用,CyclicBarrier 可循环使用
- Semaphore 可动态调整许可,支持公平/非公平模式
📝 发现内容有误?点击此处直接编辑