好的,我来为你详细讲解 Java 并发工具类 CountDownLatch 的理解和使用 👇
1. 什么是 CountDownLatch
CountDownLatch
是 java.util.concurrent
包下的一个同步辅助类,常用于 线程等待协调 的场景。
它的主要功能是:
- 一个或多个线程 等待 其他线程完成一组操作 后再继续执行。
通俗理解:像一个倒计时锁,初始化一个计数值(count),每次调用
countDown()
方法,计数器减 1;当计数器为 0 时,等待的线程会被唤醒继续执行。
2. 构造方法
public CountDownLatch(int count)
count
:初始计数值,表示需要多少个事件完成后才能继续。
3. 常用方法
await()
- 让当前线程等待,直到计数器为 0 才继续。
- 可带超时参数:
await(long timeout, TimeUnit unit)
。
countDown()
- 将计数器减 1,表示完成一个任务。
- 当计数器减到 0 时,所有等待的线程会被释放。
getCount()
- 获取当前剩余的计数值。
4. 应用场景
- 并行任务等待汇总:主线程等待多个子任务完成。
- 模拟并发场景:比如压测,多个线程同时执行。
- 控制线程执行顺序:比如让线程 B 等待线程 A 执行完成。
5. 使用示例
示例 1:等待多个任务完成
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int taskCount = 3;
CountDownLatch latch = new CountDownLatch(taskCount);
for (int i = 0; i < taskCount; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " 开始执行任务...");
try {
Thread.sleep(1000); // 模拟任务执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 完成任务!");
latch.countDown(); // 任务完成,计数器减一
}).start();
}
System.out.println("主线程等待所有子任务完成...");
latch.await(); // 等待计数器归零
System.out.println("所有子任务已完成,主线程继续执行。");
}
}
运行结果:
Thread-0 开始执行任务...
Thread-1 开始执行任务...
Thread-2 开始执行任务...
主线程等待所有子任务完成...
Thread-0 完成任务!
Thread-1 完成任务!
Thread-2 完成任务!
所有子任务已完成,主线程继续执行。
示例 2:模拟并发执行(类似并发测试)
import java.util.concurrent.CountDownLatch;
public class ConcurrencyTest {
public static void main(String[] args) throws InterruptedException {
int threadCount = 5;
CountDownLatch startSignal = new CountDownLatch(1); // 开始信号
CountDownLatch doneSignal = new CountDownLatch(threadCount); // 结束信号
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
startSignal.await(); // 等待开始信号
System.out.println(Thread.currentThread().getName() + " 同时开始执行任务");
Thread.sleep((long)(Math.random() * 2000));
doneSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
System.out.println("所有线程准备就绪,3 秒后同时开始...");
Thread.sleep(3000);
startSignal.countDown(); // 释放开始信号
doneSignal.await(); // 等待所有线程完成
System.out.println("所有线程任务执行完毕!");
}
}
6. 注意事项
CountDownLatch
是一次性的,计数器一旦归零,就不能重置。- 如果需要重复使用,可以考虑
CyclicBarrier
或Semaphore
。
- 如果需要重复使用,可以考虑
- 调用
countDown()
不会阻塞线程,它只是减少计数器。 await()
才是阻塞当前线程的方法。
✅ 总结一句话:
CountDownLatch 适合用于 “一个或多个线程等待一组操作完成后再执行” 的场景。
发表回复