星驰编程网

免费编程资源分享平台_编程教程_代码示例_开发技术文章

CountDownLatch 有什么用(countdownlatch的await)

一句话总结

CountDownLatch 用于同步线程,允许一个或多个线程等待其他线程完成操作。初始化时设定计数器,线程完成任务后调用 countDown() 减少计数,当计数器归零时,等待的线程被唤醒。常用于主线程等待多个子线程初始化完成,或控制多个线程同时开始执行任务。

详细解析

CountDownLatch 是 Java 并发包(java.util.concurrent)中的同步工具类,其核心作用是 协调多个线程的执行顺序,允许一个或多个线程等待其他线程完成操作后再继续执行。以下是其核心用途、工作原理及典型场景的详细解析:


一、核心功能与作用

  1. 等待多个线程完成
    主线程(或某个线程)需要等待多个子线程执行完毕后再继续处理后续逻辑。
    示例:主线程等待所有服务初始化完成后再启动业务逻辑。
  2. 控制并行任务的起始点
    多个线程在某一时刻同时开始执行任务(如赛跑发令枪)。
    示例:同时启动多个线程进行数据处理,确保所有线程同时进入执行阶段。
  3. 实现最大并行性
    通过等待所有线程就绪后同时释放,最大化资源利用率。

二、工作原理

  1. 计数器机制
    o 初始化时设定一个计数值count,表示需要等待的任务数量。
  2. o 每个任务完成后调用countDown()方法将计数器减 1。
  3. o 当计数器减至 0 时,所有调用await()的线程被唤醒。
  4. 底层依赖 AQS
    基于AbstractQueuedSynchronizer(AQS)实现,通过同步状态(state)管理计数器,线程阻塞和唤醒由 AQS 的队列控制。

三、典型应用场景

1、主线程等待子线程完成
场景:主线程需要汇总多个子线程的计算结果。
代码示例:

CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 子线程执行任务
        latch.countDown();
    }).start();
}
latch.await(); // 主线程等待所有子线程完成
System.out.println("所有子线程已完成,主线程继续执行");

输出:

子线程1完成
子线程2完成
子线程3完成
所有子线程已完成,主线程继续执行

2、多服务依赖启动
场景:主服务需等待数据库、缓存等依赖服务启动完成后才能运行。
代码示例:

CountDownLatch serviceLatch = new CountDownLatch(3);
// 启动数据库服务
new Thread(() -> {
    startDatabase();
    serviceLatch.countDown();
}).start();
// 启动缓存服务
new Thread(() -> {
    startCache();
    serviceLatch.countDown();
}).start();
serviceLatch.await(); // 等待所有服务启动
startMainService();

3、模拟并发测试
场景:模拟多个用户同时发起请求,测试系统性能。
代码示例:

CountDownLatch startLatch = new CountDownLatch(1); // 发令枪
CountDownLatch endLatch = new CountDownLatch(100); // 等待100个线程完成
for (int i = 0; i < 100; i++) {
    new Thread(() -> {
        try {
            startLatch.await(); // 等待发令枪响
            sendRequest(); // 模拟请求
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            endLatch.countDown();
        }
    }).start();
}
startLatch.countDown(); // 开始测试
endLatch.await(); // 等待所有请求完成

4、任务分阶段执行
场景:将任务拆分为多个阶段,每个阶段需等待前一阶段完成。
示例:

CountDownLatch phase1Latch = new CountDownLatch(5);
CountDownLatch phase2Latch = new CountDownLatch(5);
// 阶段1:数据预处理
for (int i = 0; i < 5; i++) {
    new Thread(() -> {
        preprocessData();
        phase1Latch.countDown();
    }).start();
}
phase1Latch.await(); // 等待阶段1完成
// 阶段2:数据分析
for (int i = 0; i < 5; i++) {
    new Thread(() -> {
        analyzeData();
        phase2Latch.countDown();
    }).start();
}
phase2Latch.await(); // 等待阶段2完成

四、与 CyclicBarrier 的区别

特性

CountDownLatch

CyclicBarrier

计数器重置

一次性使用,计数器归零后不可重置

可重复使用,计数器归零后自动重置

等待方向

一个或多个线程等待其他线程完成

所有线程相互等待,直到全部到达屏障点

典型用途

任务汇总、服务依赖启动

分阶段任务协调(如多阶段计算)



控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言