编写一个示例程序,展示如何使用 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.

代码解析

  1. CountDownLatch 初始化
    • CountDownLatch latch = new CountDownLatch(3);
    • 创建一个 CountDownLatch,初始计数器值为 3,表示需要等待 3 个任务完成。
  2. 工作线程的任务
    • 每个工作线程模拟执行某些任务(通过 Thread.sleep 模拟耗时操作)。
    • 执行完任务后调用 latch.countDown(),将计数器减 1。
  3. 主线程等待
    • latch.await(); 会阻塞主线程,直到计数器值变为 0。
  4. 工作线程完成后继续主线程
    • 当计数器值为 0 时,await() 方法返回,主线程继续执行。

扩展:并行任务的启动和同步

我们也可以使用 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是一个很好的多线程同步工具,可以用于:
    1. 主线程等待多个子线程完成任务。
    2. 控制多个线程同时启动。
  • 核心方法:
    • countDown():让计数器减 1。
    • await():阻塞线程,直到计数器为 0。
  • 适合使用场景:
    • 并行任务的启动和同步。
    • 主线程等待子线程完成任务。
    • 模拟比赛等需要同步的场景。

发表评论

后才能评论