CountDownLatch详解


前言

CountDownLatch(闭锁)是一个同步协助类,允许一个或多个线程等待,直到其他线程完成操作集。

在这里插入图片描述
CountDownLatch使用给定的计数值(count)初始化。await方法会阻塞直到当前的计数值(count),由于countDown方法的调用达到0,count为0之后所有等待的线程都会被释放,并且随后对await方法的调用都会立即返回。这是一个一次性现象 —— count不会被重置。

常用API

构造器

    /**
     * Constructs a {@code CountDownLatch} initialized with the given count.
     *
     * @param count the number of times {@link #countDown} must be invoked
     *        before threads can pass through {@link #await}
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

常用方法

//调用 await() 方法的线程会被挂起,它会等待直到 count 值为 0 才继续执行
public void await() throws InterruptedException {}
//和 await() 类似,若等待 timeout 时长后,count 值还是没有变为 0,不再等待,继续执行
public boolean await(long timeout, TimeUnit unit)throws InterruptedException  {}
//会将 count 减 1,直至为 0
public void countDown() {}

CountDownLatch使用

模拟实现百米赛跑

代码如下(示例):

public class CountDownLatchDemo {
    private static CountDownLatch pre = new CountDownLatch(8);
    private static CountDownLatch begin = new CountDownLatch(1);
    private static CountDownLatch end = new CountDownLatch(8);
    public static void main(String[] args) throws InterruptedException {
        for(int i = 0;i<8;i++){
            new Thread(()->{

                try {
                    Thread.sleep(new Random().nextInt(1000,3000));
                    System.out.println("参赛者"+Thread.currentThread().getName()+"已经准备好");
                    pre.countDown(); //准备完毕,计数器减一
                    begin.await(); //等待裁判吹哨
                    System.out.println("参赛者"+Thread.currentThread().getName()+"开始奔跑");
                    Thread.sleep(new Random().nextInt(1000,5000));
                    System.out.println("参赛者"+Thread.currentThread().getName()+"到达终点");
                    end.countDown();//参赛者到达终点,计数器减一
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }
        pre.await(); //等待所有参赛者准备
        System.out.println("所有参赛者准备完毕");
        begin.countDown(); //所有参赛者准备完毕就开始吹哨
        end.await(); //等待所有参赛者到达终点
        System.out.println("比赛结束");

    }
}
/**
 * 参赛者Thread-6已经准备好
 * 参赛者Thread-1已经准备好
 * 参赛者Thread-4已经准备好
 * 参赛者Thread-2已经准备好
 * 参赛者Thread-7已经准备好
 * 参赛者Thread-0已经准备好
 * 参赛者Thread-3已经准备好
 * 参赛者Thread-5已经准备好
 * 所有参赛者准备完毕
 * 参赛者Thread-2开始奔跑
 * 参赛者Thread-3开始奔跑
 * 参赛者Thread-0开始奔跑
 * 参赛者Thread-6开始奔跑
 * 参赛者Thread-4开始奔跑
 * 参赛者Thread-1开始奔跑
 * 参赛者Thread-7开始奔跑
 * 参赛者Thread-5开始奔跑
 * 参赛者Thread-0到达终点
 * 参赛者Thread-4到达终点
 * 参赛者Thread-5到达终点
 * 参赛者Thread-6到达终点
 * 参赛者Thread-7到达终点
 * 参赛者Thread-1到达终点
 * 参赛者Thread-2到达终点
 * 参赛者Thread-3到达终点
 * 比赛结束
 */

多任务完成后合并汇总

很多时候,我们的并发任务,存在前后依赖关系;比如数据详情页需要同时调用多个接口获取数据,并发请求获取到数据后、需要进行结果合并;或者多个数据操作完成后,需要数据check。

代码如下(示例):

public class CountDownLatchDemo2 {
    
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i=0;i<5;i++){
            final int index = i;
            new Thread(()->{
                try {
                    Thread.sleep(1000+ ThreadLocalRandom.current().nextInt(2000));
                    System.out.println("任务"+index+"执行完成");
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }

        countDownLatch.await();
        System.out.println("主线程:在所有任务运行完成后,进行结果汇总");
    }
}
/**
 * 任务0执行完成
 * 任务1执行完成
 * 任务4执行完成
 * 任务2执行完成
 * 任务3执行完成
 * 主线程:在所有任务运行完成后,进行结果汇总
 */

应用场景总结

以下是使用CountDownLatch的常见场景:

  1. 并行任务同步:CountDownLatch可以用于协调多个并行任务的完成情况,确保所有任务都完成后再继续执行下
    一步操作。
  2. 多任务汇总:CountDownLatch可以用于统计多个线程的完成情况,以确定所有线程都已完成工作。
  3. 资源初始化:CountDownLatch可以用于等待资源的初始化完成,以便在资源初始化完成后开始使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值