在使用 ThreadPoolExecutor 执行多个任务时,有时需要等待所有任务完成后再执行下一步操作。可以使用 ExecutorService 的 invokeAll() 方法或者结合 CountDownLatch 来实现这一功能。
- invokeAll() 方法:
- 适用于 Callable 任务,简单明了地等待所有任务完成,并收集结果。
- CountDownLatch:
- 适用于 Runnable 任务,提供了更灵活的控制,可以在任务执行过程中进行其他操作。
两种方式都能有效地保证在所有线程完成任务后再执行后续操作,选择哪种方式取决于具体的使用场景和任务类型。
CountDownLatch
CountDownLatch
是 Java 并发包中的一个同步辅助工具类,允许一个或多个线程等待直到一组操作完成。它可以用于实现任务的协调,确保某些线程在继续执行之前等待其他线程完成任务。
CountDownLatch 是一个计数的闭锁,作用与 CyclicBarrier 有点儿相似。CountDownLatch 是通过一个计数器来实现的,计数器的初始值为任务的数量。每当一个线程完成了一个任务后,计数器的值就会减1。当计数器值到达0时,它表示多线程已经完成了所有任务,然后就可以恢复等待的线程继续执行了。
工作原理:
- 初始化时设置计数器的值为需要等待的线程任务数量。
- 每当一个任务完成任务时,调用 countDown() 方法将计数器减 1。
- 当计数器的值达到 0 时,所有等待的线程将被唤醒,继续执行。
使用场景
CountDownLatch 常用于以下场景:
- 在所有线程完成某些子任务之前,不让主线程继续执行。
- 等待多个线程执行完毕后再执行下一步操作。
示例:多个线程完成任务后主线程继续执行
import java.util.concurrent.CountDownLatch;
class MyRunnable implements Runnable {
private final CountDownLatch latch;
private final int taskId;
public MyRunnable(CountDownLatch latch, int taskId) {
this.latch = latch;
this.taskId = taskId;
}
@Override
public void run() {
try {
// 模拟任务执行
System.out.println("Task " + taskId + " is running in thread: " + Thread.currentThread().getName());
Thread.sleep((long) (Math