编写一个示例程序,展示如何使用 CountDownLatch 类进行多线程同步和协作。
以下是一个示例程序,展示如何使用 CountDownLatch
类来进行多线程同步和协作:
示例程序:使用 CountDownLatch
等待多个线程完成任务
场景描述:
主线程需要等待多个工作线程完成各自的任务后,继续执行。例如,在一个比赛中,需要等所有选手准备好后,裁判才发出开始信号。
代码实现
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) {
// 创建 CountDownLatch,计数器初始值为 3,表示需要等待 3 个线程完成任务
CountDownLatch latch = new CountDownLatch(3);
// 创建并启动 3 个工作线程
for (int i = 1; i <= 3; i++) {
int threadNumber = i; // 用于线程标识
new Thread(() -> {
try {
System.out.println("Worker " + threadNumber + " is working...");
Thread.sleep((long) (Math.random() * 3000)); // 模拟任务执行时间
System.out.println("Worker " + threadNumber + " has finished.");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown(); // 每个线程完成任务后,计数器减 1
}
}).start();
}
// 主线程等待所有工作线程完成任务
try {
System.out.println("Main thread is waiting for workers to finish...");
latch.await(); // 等待计数器归零
System.out.println("All workers have finished. Main thread resumes.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
程序输出(示例)
输出顺序可能因线程调度不同而变化:
Main thread is waiting for workers to finish...
Worker 1 is working...
Worker 2 is working...
Worker 3 is working...
Worker 2 has finished.
Worker 1 has finished.
Worker 3 has finished.
All workers have finished. Main thread resumes.
代码解析
CountDownLatch
初始化:CountDownLatch latch = new CountDownLatch(3);
- 创建一个
CountDownLatch
,初始计数器值为3
,表示需要等待 3 个任务完成。
- 工作线程的任务:
- 每个工作线程模拟执行某些任务(通过
Thread.sleep
模拟耗时操作)。 - 执行完任务后调用
latch.countDown()
,将计数器减 1。
- 每个工作线程模拟执行某些任务(通过
- 主线程等待:
latch.await();
会阻塞主线程,直到计数器值变为 0。
- 工作线程完成后继续主线程:
- 当计数器值为 0 时,
await()
方法返回,主线程继续执行。
- 当计数器值为 0 时,
扩展:并行任务的启动和同步
我们也可以使用 CountDownLatch
控制多个线程同时启动。例如,模拟多个线程同时启动任务(如多个跑步选手听到发令枪声同时开始比赛)。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchRaceExample {
public static void main(String[] args) {
CountDownLatch readyLatch = new CountDownLatch(1); // 控制选手开始的信号
CountDownLatch finishLatch = new CountDownLatch(3); // 等待所有选手完成
// 创建并启动 3 个选手线程
for (int i = 1; i <= 3; i++) {
int threadNumber = i;
new Thread(() -> {
try {
System.out.println("Runner " + threadNumber + " is ready...");
readyLatch.await(); // 等待发令信号
System.out.println("Runner " + threadNumber + " started running!");
Thread.sleep((long) (Math.random() * 3000)); // 模拟跑步时间
System.out.println("Runner " + threadNumber + " finished!");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
finishLatch.countDown(); // 每个选手跑完后,计数器减 1
}
}).start();
}
try {
Thread.sleep(1000); // 模拟准备时间
System.out.println("Ready... Set... Go!");
readyLatch.countDown(); // 发令信号,所有线程开始运行
finishLatch.await(); // 等待所有选手完成
System.out.println("All runners have finished the race!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
程序输出(示例)
输出顺序可能因线程调度不同而变化:
Runner 1 is ready...
Runner 2 is ready...
Runner 3 is ready...
Ready... Set... Go!
Runner 1 started running!
Runner 3 started running!
Runner 2 started running!
Runner 3 finished!
Runner 1 finished!
Runner 2 finished!
All runners have finished the race!
总结
- CountDownLatch是一个很好的多线程同步工具,可以用于:
- 主线程等待多个子线程完成任务。
- 控制多个线程同时启动。
- 核心方法:
countDown()
:让计数器减 1。await()
:阻塞线程,直到计数器为 0。
- 适合使用场景:
- 并行任务的启动和同步。
- 主线程等待子线程完成任务。
- 模拟比赛等需要同步的场景。