一、CountDownLatch
-
CountDownLatch 是 Java 并发编程中的一个同步工具类,用于协调多个线程的执行
-
CountDownLatch 允许一个或多个线程等待其他线程完成操作后再继续执行
-
CountDownLatch 的核心思想是通过一个计数器来实现线程的等待和通知机制
二、CountDownLatch 核心功能
1、计数器
-
CountDownLatch 内部维护一个计数器,初始值为指定的正整数
-
每当一个线程完成任务时,调用 countDown 方法将计数器减 1
-
当计数器减到 0 时,所有等待的线程会被唤醒并继续执行
2、等待机制
-
线程可以调用 await 方法等待计数器减到 0
-
如果计数器不为 0,调用 await 方法的线程会被阻塞,直到计数器减到 0
三、CountDownLatch 核心方法
CountDownLatch(int count)
- 构造方法,初始化计数器
void await() throws InterruptedException
- 等待计数器减到 0,如果计数器不为 0,则当前线程会被阻塞
boolean await(long timeout, TimeUnit unit) throws InterruptedException
- 等待计数器减到 0,最多等待指定时间,如果超时返回 false,否则返回 true
void countDown()
- 将计数器减 1,如果计数器减到 0,则唤醒所有等待的线程
long getCount()
- 返回当前计数器的值
四、CountDownLatch 实例实操
1、主线程等待子线程完成任务
int threadCount = 3;
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 1; i <= threadCount; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is working...");
Thread.sleep((long) (Math.random() * 1000)); // 模拟任务执行时间
System.out.println(Thread.currentThread().getName() + " has finished");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 任务完成,计数器减 1
}
}, "Thread-" + i).start();
}
System.out.println("Main thread is waiting for all threads to finish...");
try {
latch.await(); // 主线程等待计数器减到 0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All threads have finished. Main thread continues");
- 输出结果
Main thread is waiting for all threads to finish...
Thread-3 is working...
Thread-2 is working...
Thread-1 is working...
Thread-1 has finished
Thread-3 has finished
Thread-2 has finished
All threads have finished. Main thread continues
2、多线程任务同步
int threadCount = 3;
CountDownLatch startLatch = new CountDownLatch(1); // 用于同步开始
CountDownLatch endLatch = new CountDownLatch(threadCount); // 用于等待结束
for (int i = 1; i <= threadCount; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is ready");
startLatch.await(); // 等待主线程发出开始信号
System.out.println(Thread.currentThread().getName() + " is running...");
Thread.sleep((long) (Math.random() * 1000)); // 模拟任务执行时间
System.out.println(Thread.currentThread().getName() + " has finished");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
endLatch.countDown(); // 任务完成,计数器减 1
}
}, "Thread-" + i).start();
}
try {
Thread.sleep(1000); // 模拟主线程准备时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main thread signals to start");
startLatch.countDown(); // 发出开始信号
System.out.println("Main thread is waiting for all threads to finish...");
try {
endLatch.await(); // 主线程等待所有线程完成任务
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All threads have finished. Main thread continues");
- 输出结果
Thread-1 is ready
Thread-3 is ready
Thread-2 is ready
Main thread signals to start
Main thread is waiting for all threads to finish...
Thread-1 is running...
Thread-3 is running...
Thread-2 is running...
Thread-1 has finished
Thread-2 has finished
Thread-3 has finished
All threads have finished. Main thread continues
3、分阶段任务处理
int threadCount = 3;
CountDownLatch phaseLatch = new CountDownLatch(threadCount);
for (int i = 1; i <= threadCount; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " is working on phase 1...");
Thread.sleep((long) (Math.random() * 1000)); // 模拟任务执行时间
System.out.println(Thread.currentThread().getName() + " has finished phase 1");
phaseLatch.countDown(); // 第一阶段完成,计数器减 1
phaseLatch.await(); // 等待所有线程完成第一阶段
System.out.println(Thread.currentThread().getName() + " is working on phase 2...");
Thread.sleep((long) (Math.random() * 1000)); // 模拟任务执行时间
System.out.println(Thread.currentThread().getName() + " has finished phase 2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "Thread-" + i).start();
}
- 输出结果
Thread-1 is working on phase 1...
Thread-3 is working on phase 1...
Thread-2 is working on phase 1...
Thread-3 has finished phase 1
Thread-2 has finished phase 1
Thread-1 has finished phase 1
Thread-3 is working on phase 2...
Thread-1 is working on phase 2...
Thread-2 is working on phase 2...
Thread-2 has finished phase 2
Thread-1 has finished phase 2
Thread-3 has finished phase 2