使用Java CountDownLatch实现线程池
在多线程编程中,CountDownLatch
是一个非常有用的工具,它可以让一个或多个线程等待其他线程完成后再继续执行。下面我们将通过一个实例来学习如何结合使用 CountDownLatch
和线程池。
流程概述
我们需要完成的任务是:使用线程池启动多个任务,使用 CountDownLatch
等待所有任务完成。下面的表格展示了整个实现的步骤:
步骤 | 描述 |
---|---|
1 | 创建线程池 |
2 | 初始化 CountDownLatch |
3 | 提交多个任务到线程池 |
4 | 等待所有任务完成 |
5 | 处理完成后的操作 |
实现步骤
接下来,我们逐步实现上述步骤。
步骤 1: 创建线程池
我们使用 Executors.newFixedThreadPool
创建一个固定大小的线程池。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
ExecutorService executor = Executors.newFixedThreadPool(5); // 创建一个固定大小为5的线程池
步骤 2: 初始化 CountDownLatch
我们使用 CountDownLatch
来跟踪任务的完成情况。通过传入任务的数量来初始化 CountDownLatch
。
import java.util.concurrent.CountDownLatch;
int taskCount = 10; // 假设我们有10个任务要执行
CountDownLatch latch = new CountDownLatch(taskCount); // 初始化 CountDownLatch
步骤 3: 提交多个任务到线程池
接下来,我们提交任务到线程池。每个任务在执行时调用 latch.countDown()
来减少计数。
for (int i = 0; i < taskCount; i++) {
int taskId = i; // 定义任务ID
executor.submit(() -> {
try {
// 模拟任务执行
System.out.println("Executing task " + taskId);
Thread.sleep(1000); // 模拟任务耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
} finally {
latch.countDown(); // 每个任务完成后调用 countDown
}
});
}
步骤 4: 等待所有任务完成
在提交完所有任务后,我们调用 await()
方法,这样就会阻塞主线程,直到所有任务完成。
try {
latch.await(); // 等待所有任务完成
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
}
步骤 5: 处理完成后的操作
所有任务完成后,可以在这里进行后续处理,例如释放资源或输出结果。
System.out.println("All tasks are completed.");
executor.shutdown(); // 关闭线程池
完整代码示例
将所有步骤整合起来,完整的实现代码如下:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountDownLatchExample {
public static void main(String[] args) {
int taskCount = 10;
CountDownLatch latch = new CountDownLatch(taskCount);
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < taskCount; i++) {
int taskId = i;
executor.submit(() -> {
try {
System.out.println("Executing task " + taskId);
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
latch.countDown();
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("All tasks are completed.");
executor.shutdown();
}
}
甘特图
接下来是表示任务流程的甘特图,展示任务的执行过程:
gantt
title Tasks Execution
dateFormat YYYY-MM-DD
section Tasks
Execute Task 1 :a1, 2023-10-01, 1d
Execute Task 2 :a2, 2023-10-01, 1d
Execute Task 3 :a3, 2023-10-01, 1d
Execute Task 4 :a4, 2023-10-01, 1d
Execute Task 5 :a5, 2023-10-01, 1d
Execute Task 6 :a6, 2023-10-01, 1d
Execute Task 7 :a7, 2023-10-01, 1d
Execute Task 8 :a8, 2023-10-01, 1d
Execute Task 9 :a9, 2023-10-01, 1d
Execute Task 10 :a10, 2023-10-01, 1d
状态图
以下是任务的状态图,展示任务的执行和完成状态:
stateDiagram
[*] --> 不可执行
不可执行 --> 任务执行中: 提交任务
任务执行中 --> 可执行: 任务完成
可执行 --> [*]
结尾
通过以上几个步骤,我们成功地使用 CountDownLatch
和线程池实现了一个简单的多线程任务执行模型。希望这篇文章能帮助您更好地理解如何使用 Java 的并发工具,期待您在多线程的路上越走越远!