Java中如何使用CountDownLatch实现线程等待

2026年03月19日/ 浏览 5

正文:

在Java多线程编程中,线程同步是一个常见且复杂的问题。CountDownLatch作为java.util.concurrent包下的重要工具,能够优雅地实现线程间的等待机制。本文将深入解析CountDownLatch的使用方法,并结合实际代码示例,帮助你掌握其核心技巧。

1. CountDownLatch的核心原理

CountDownLatch通过一个计数器实现线程阻塞与唤醒。初始化时指定计数值(例如N),每当一个线程完成任务时调用countDown()方法,计数器减1。当计数器归零时,所有调用await()方法等待的线程会被唤醒,继续执行后续逻辑。

2. 基础用法示例

以下是一个典型场景:主线程等待多个子线程完成任务后再继续执行。

import java.util.concurrent.CountDownLatch;

public class BasicExample {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            new Thread(() -> {
                System.out.println("子线程" + Thread.currentThread().getId() + "执行任务");
                latch.countDown(); // 计数器减1
            }).start();
        }

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

3. 实践技巧与注意事项

  • 避免死锁:确保所有线程最终都会调用countDown(),否则主线程可能永久阻塞。
  • 复用问题CountDownLatch的计数器不可重置,若需重复使用,可考虑CyclicBarrier
  • 超时机制await(long timeout, TimeUnit unit)方法可设置超时时间,防止无限等待。

4. 典型应用场景

  • 批量任务并行处理:例如分布式系统中等待多个服务返回结果后聚合数据。
  • 模拟高并发测试:使用CountDownLatch协调多个线程同时触发请求。
  • 初始化资源等待:确保所有依赖资源就绪后再启动主逻辑。

5. 进阶示例:多阶段任务协调

以下代码展示如何分阶段控制线程执行顺序:

public class MultiStageExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch stage1Latch = new CountDownLatch(2);
        CountDownLatch stage2Latch = new CountDownLatch(1);

        new Thread(() -> {
            System.out.println("阶段1-任务A开始");
            stage1Latch.countDown();
        }).start();

        new Thread(() -> {
            System.out.println("阶段1-任务B开始");
            stage1Latch.countDown();
        }).start();

        stage1Latch.await(); // 等待阶段1完成
        System.out.println("阶段2开始");
        stage2Latch.countDown(); // 触发阶段2
    }
}

总结

CountDownLatch是Java多线程编程中的“信号枪”,通过简洁的API实现复杂的线程协作。合理使用它可以大幅提升程序的健壮性和可维护性。建议结合具体业务场景灵活设计计数器逻辑,并注意异常处理和资源释放,避免潜在问题。

picture loss