CountDownLatch使用
介绍
在并发编程中,协调多个线程的执行顺序是一个常见的需求。Java提供了多种工具来实现线程同步,其中之一就是 CountDownLatch
。CountDownLatch
是一个同步辅助类,允许一个或多个线程等待其他线程完成操作后再继续执行。
CountDownLatch
的核心思想是通过一个计数器来实现线程的等待。计数器初始化为一个正整数,表示需要等待的线程数量。每当一个线程完成了它的任务,计数器就会减一。当计数器减到零时,等待的线程就会被唤醒,继续执行。
基本用法
CountDownLatch
的主要方法有两个:
countDown()
:将计数器减一。await()
:使当前线程等待,直到计数器减到零。
代码示例
以下是一个简单的示例,展示了如何使用 CountDownLatch
来协调多个线程的执行:
java
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
int numThreads = 3;
CountDownLatch latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; 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();
}
latch.await(); // 主线程等待所有任务完成
System.out.println("所有任务已完成,主线程继续执行");
}
}
输出
Thread-0 正在执行任务...
Thread-1 正在执行任务...
Thread-2 正在执行任务...
Thread-0 任务完成
Thread-1 任务完成
Thread-2 任务完成
所有任务已完成,主线程继续执行
在这个示例中,主线程创建了三个子线程,每个子线程执行一个任务。主线程通过 latch.await()
等待所有子线程完成任务。每个子线程完成任务后调用 latch.countDown()
,当所有子线程都完成任务后,主线程继续执行。
实际应用场景
CountDownLatch
在实际开发中有很多应用场景,例如:
- 多线程任务同步:在多个线程执行任务时,主线程需要等待所有子线程完成任务后再继续执行。
- 并行计算:在并行计算中,多个线程分别计算一部分结果,主线程等待所有线程计算完成后汇总结果。
- 资源初始化:在系统启动时,多个资源需要初始化,主线程等待所有资源初始化完成后再继续执行。
示例:并行计算
假设我们需要计算一个大数组的和,可以将数组分成多个部分,每个线程计算一部分的和,最后主线程汇总所有部分的和。
java
import java.util.concurrent.CountDownLatch;
public class ParallelSum {
public static void main(String[] args) throws InterruptedException {
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numThreads = 2;
CountDownLatch latch = new CountDownLatch(numThreads);
int[] partialSums = new int[numThreads];
for (int i = 0; i < numThreads; i++) {
final int threadIndex = i;
new Thread(() -> {
int start = threadIndex * (array.length / numThreads);
int end = (threadIndex + 1) * (array.length / numThreads);
for (int j = start; j < end; j++) {
partialSums[threadIndex] += array[j];
}
latch.countDown();
}).start();
}
latch.await();
int totalSum = 0;
for (int sum : partialSums) {
totalSum += sum;
}
System.out.println("数组的总和为: " + totalSum);
}
}
输出
数组的总和为: 55
在这个示例中,我们将数组分成两部分,分别由两个线程计算部分和。主线程等待两个线程计算完成后,汇总部分和得到最终结果。
总结
CountDownLatch
是一个非常有用的工具,可以帮助我们在多线程环境中实现线程同步。通过 CountDownLatch
,我们可以确保某些线程在其他线程完成特定任务后再继续执行。这在并行计算、资源初始化等场景中非常有用。
提示
在使用 CountDownLatch
时,确保计数器的初始值正确设置,并且在每个线程完成任务后调用 countDown()
方法。
附加资源
练习
- 修改上面的并行计算示例,使其支持任意数量的线程。
- 尝试使用
CountDownLatch
实现一个简单的任务调度系统,主线程等待所有任务完成后输出“所有任务已完成”。