CountDownLatch简单介绍


一、CountDownLatch是什么?

  CountDownLatch是一个同步工具类,在java.util.cucurrent包中,是JUC编程中较为常用的一个工具类,允许一个或多个线程一直等待,直到其他线程运行完成后再执行。
  它的的实现简单来说是通过一个计数器,初始化的时候给计时器一个指定值,然后在子线程中当执行完规定的逻辑后,计数器会进行减1操作,当计数器为0时,那么在阻塞等待的线程则会被唤醒恢复执行。

二、使用示例

  CountDownLatch的使用一般可分为两种场景:

  • 场景1:多个线程等待另一个
  • 场景2:一个等待多个线程

1、场景1

  这个就相当于是一组线程在准备就绪后,等待某个指定的时刻一起并发执行(秒杀),就像我们上高中时,早自习结束铃声一响,全体立马抄家伙冲向食堂~

public class Main4 {


    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(1);

        // 简单直接的new线程了,也可以用线程池
        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ":民以食为天,我等...");
                countDownLatch.await(); // 阻塞,等待计数器值为0后再往下执行
                System.out.println(Thread.currentThread().getName() + ":走着~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"傻蛋").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ":激动的心,颤抖的手,我也等...");
                countDownLatch.await(); // 阻塞,等待计数器值为0后再往下执行
                System.out.println(Thread.currentThread().getName() + ":食堂,我来了~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"狗蛋").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ":兄弟们,准备抄家伙...");
                countDownLatch.await(); // 阻塞,等待计数器值为0后再往下执行
                System.out.println(Thread.currentThread().getName() + ":冲鸭~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        },"毛蛋").start();

        // 主线程休眠1秒后,计数器减1
        Thread.sleep(1000);
        countDownLatch.countDown();

        System.out.println("铃声响起!");
    }

}

执行结果:

傻蛋:民以食为天,我等…
狗蛋:激动的心,颤抖的手,我也等…
毛蛋:兄弟们,准备抄家伙…
铃声响起!
傻蛋:走着~
毛蛋:冲鸭~
狗蛋:食堂,我来了~

2、场景2

  有的时候并发任务可能存在一些前后依赖关系,就好比我需要做一个当月的销售数据分析,那么我通过多个线程去不同的数据表读取数据,读取完后再进行统一分析处理。

public class Main5 {


    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(3);

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "读取订单数据...");
                Thread.sleep(700);
                System.out.println(Thread.currentThread().getName() + "读取完成!");
                countDownLatch.countDown(); // 子线程执行完后,计数减1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t1").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "读取支付数据...");
                Thread.sleep(500);
                System.out.println(Thread.currentThread().getName() + "读取完成!");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t2").start();

        new Thread(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + "读取会员数据...");
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + "读取完成!");
                countDownLatch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"t3").start();

        // 阻塞,等待所有线程执行完成后再往下执行
        countDownLatch.await();

        System.out.println("数据加载完成,开始分析");
    }

}

运行结果:

t1读取订单数据…
t2读取支付数据…
t3读取会员数据…
t2读取完成!
t1读取完成!
t3读取完成!
数据加载完成,开始分析

三、小结

  CountDownLatch看起来是有点类似join() 方法,但是用起来比join()更加灵活。CountDownLatch可以在n个线程中调用n次减1操作,也可以在一个线程中调用n次减1操作。但是CountDownLatch是一次性的,计算器的初始值只能被初始化一次,当CountDownLatch使用完毕后不能再次被使用,所以这也就有了CyclicBarrier。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值