跳到主要内容

CountDownLatch使用

介绍

在并发编程中,协调多个线程的执行顺序是一个常见的需求。Java提供了多种工具来实现线程同步,其中之一就是 CountDownLatchCountDownLatch 是一个同步辅助类,允许一个或多个线程等待其他线程完成操作后再继续执行。

CountDownLatch 的核心思想是通过一个计数器来实现线程的等待。计数器初始化为一个正整数,表示需要等待的线程数量。每当一个线程完成了它的任务,计数器就会减一。当计数器减到零时,等待的线程就会被唤醒,继续执行。

基本用法

CountDownLatch 的主要方法有两个:

  1. countDown():将计数器减一。
  2. 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 在实际开发中有很多应用场景,例如:

  1. 多线程任务同步:在多个线程执行任务时,主线程需要等待所有子线程完成任务后再继续执行。
  2. 并行计算:在并行计算中,多个线程分别计算一部分结果,主线程等待所有线程计算完成后汇总结果。
  3. 资源初始化:在系统启动时,多个资源需要初始化,主线程等待所有资源初始化完成后再继续执行。

示例:并行计算

假设我们需要计算一个大数组的和,可以将数组分成多个部分,每个线程计算一部分的和,最后主线程汇总所有部分的和。

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() 方法。

附加资源

练习

  1. 修改上面的并行计算示例,使其支持任意数量的线程。
  2. 尝试使用 CountDownLatch 实现一个简单的任务调度系统,主线程等待所有任务完成后输出“所有任务已完成”。