面试题:什么是 Java 的 CountDownLatch?

CountDownLatch 是 Java 并发包 (java.util.concurrent) 中的一个同步工具类,用于让一个或多个线程等待其他线程完成操作。它通过一个计数器来实现线程的等待和通知机制,适用于主线程等待多个子线程完成任务的场景。


核心概念

  1. 计数器
    • CountDownLatch 内部维护一个计数器,初始化时指定计数器的初始值。
    • 每当一个线程完成任务时,调用 countDown() 方法,计数器减 1。
    • 当计数器减到 0 时,等待的线程会被唤醒。
  2. 一次性
    • CountDownLatch 的计数器只能减少,不能重置。如果需要重复使用,可以考虑使用 CyclicBarrier

常用方法

  1. CountDownLatch(int count)
    • 构造函数,创建一个 CountDownLatch,指定计数器的初始值。
  2. await()
    • 使当前线程等待,直到计数器减到 0。
  3. countDown()
    • 将计数器减 1,表示一个线程已完成任务。
  4. getCount()
    • 返回当前计数器的值。

使用场景

  1. 主线程等待子线程完成任务
    • 例如,主线程需要等待多个子线程完成初始化操作后再继续执行。
  2. 并行任务同步
    • 多个线程并行执行任务,主线程等待所有任务完成后进行汇总。
  3. 测试多线程程序
    • 在测试中模拟多个线程同时执行任务的场景。

代码示例

以下是一个简单的 CountDownLatch 示例,模拟主线程等待多个子线程完成任务:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 CountDownLatch,计数器初始值为 3
        CountDownLatch latch = new CountDownLatch(3);

        // 创建 3 个子线程
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 开始执行任务");
                    Thread.sleep(1000); // 模拟任务执行
                    System.out.println(Thread.currentThread().getName() + " 任务完成");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 计数器减 1
                }
            }).start();
        }

        // 主线程等待所有子线程完成任务
        System.out.println("主线程等待子线程完成任务");
        latch.await();
        System.out.println("所有子线程任务完成,主线程继续执行");
    }
}

输出结果:

主线程等待子线程完成任务
Thread-0 开始执行任务
Thread-1 开始执行任务
Thread-2 开始执行任务
Thread-0 任务完成
Thread-1 任务完成
Thread-2 任务完成
所有子线程任务完成,主线程继续执行

注意事项

  1. 计数器不可重置
    • CountDownLatch 的计数器只能减少,不能重置。如果需要重复使用,可以考虑使用 CyclicBarrier
  2. 异常处理
    • 如果子线程在执行任务时抛出异常,需要确保 countDown() 方法被调用,否则主线程可能会一直等待。
  3. 性能影响
    • 如果计数器初始值设置过大,可能会导致主线程长时间等待,影响程序性能。

与 CyclicBarrier 的区别

  1. 可重用性
    • CountDownLatch 是一次性的,计数器减到 0 后不能再使用。
    • CyclicBarrier 是可重用的,屏障被打破后可以重置。
  2. 使用场景
    • CountDownLatch 适用于主线程等待多个子线程完成任务的场景。
    • CyclicBarrier 适用于多个线程互相等待,达到一个共同的屏障点后再继续执行的场景。

总结

CountDownLatch 是 Java 并发编程中用于线程同步的重要工具,适用于主线程等待多个子线程完成任务的场景。通过合理使用 CountDownLatch,可以简化多线程编程的复杂性,提高代码的可读性和可维护性。

THE END
点赞13 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容