JAVA:CountDownLatch 并发工具的技术指南

admin
7
2025-08-21

1、简述

在并发编程中,有时我们需要协调多个线程的执行,确保它们在特定的时刻同步完成。CountDownLatch是Java并发包中提供的一种强大的工具,用于实现这种同步。本文将深入探讨CountDownLatch的基本原理,以及一些实际应用场景中的巧妙应用。

image-2v5t.png


2、什么是 CountDownLatch?

2.1 基本原理

CountDownLatch 位于 java.util.concurrent 包下,它允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。

它通过一个 计数器(count) 来实现:

🔹 每调用一次 countDown(),计数器减一;
🔹 当计数器减为 0 时,所有因 await() 而阻塞的线程会被释放,继续执行后续逻辑。

简单来说:等待一批任务执行完成后,再统一往下走

image-5nux.png

2.2 常见应用场景

🔹 主线程等待多个子线程完成
比如:启动多个线程并行计算,等待所有线程完成后汇总结果。

🔹 模拟并发请求
在性能测试中,可以利用 CountDownLatch 控制多个线程同时开始执行,从而模拟高并发场景。

🔹 分阶段任务控制
有些业务逻辑需要某些步骤都完成之后,才能进入下一阶段。

2.3 使用步骤

🔹 初始化

CountDownLatch latch = new CountDownLatch(N);

N 表示需要等待的事件数量。

🔹 子线程执行任务
任务完成后调用 latch.countDown()

🔹 主线程等待
调用 latch.await(),直到计数器为 0 才继续执行。


3、实践样例

示例 1:等待多个线程完成任务

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    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(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 正在执行任务...");
                    Thread.sleep((long) (Math.random() * 2000));
                    System.out.println(Thread.currentThread().getName() + " 完成任务");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 任务完成,计数器减一
                }
            }).start();
        }

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

输出示例(顺序不固定):

主线程等待所有子线程完成任务...
Thread-0 正在执行任务...
Thread-1 正在执行任务...
Thread-2 正在执行任务...
Thread-1 完成任务
Thread-0 完成任务
Thread-2 完成任务
所有子线程执行完毕,主线程继续

示例 2:模拟并发请求

import java.util.concurrent.CountDownLatch;

public class ConcurrentTest {
    public static void main(String[] args) throws InterruptedException {
        int clientCount = 5;
        CountDownLatch startGate = new CountDownLatch(1); // 控制开始
        CountDownLatch endGate = new CountDownLatch(clientCount); // 控制结束

        for (int i = 0; i < clientCount; i++) {
            new Thread(() -> {
                try {
                    startGate.await(); // 等待一起开始
                    System.out.println(Thread.currentThread().getName() + " 发起请求");
                    Thread.sleep((long) (Math.random() * 2000));
                    System.out.println(Thread.currentThread().getName() + " 请求完成");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    endGate.countDown();
                }
            }).start();
        }

        System.out.println("准备就绪,开始并发请求!");
        startGate.countDown(); // 所有线程同时开始
        endGate.await(); // 等待所有请求完成
        System.out.println("所有请求已完成,测试结束");
    }
}

4、注意事项

🔹 一次性工具
CountDownLatch 不能重复使用。计数器归零后,就失效了。如果需要循环使用,建议使用 CyclicBarrierSemaphore

🔹 countDown() 可在不同线程调用
多个线程调用 countDown() 是线程安全的。

🔹 await() 会阻塞
如果你不希望无限等待,可以使用 await(timeout, unit) 设置超时时间。


5、总结

CountDownLatch是一个在并发编程中非常实用的工具,通过它我们可以轻松实现多个线程之间的同步。在实际应用中,可以根据不同场景灵活运用,用于任务等待、并发线程数量控制等情况。然而,在使用过程中需要注意计数器的递减和重置,以确保线程同步的正确性。通过巧妙应用CountDownLatch,可以使得并发编程更加简单、清晰、可控。

核心方法:

🔹 countDown():任务完成后调用。

🔹 await():等待所有任务完成后继续执行。

在实际项目中,它常用于 并行任务处理、性能测试、并发模拟

动物装饰