CountDownLatch简单入门

由来

在多线程的开发中,有时候会遇到线程间需要互相配合的业务操作,比如

  1. 某一个线程需要其他几个线程执行完了之后再执行 (一个等多个)
  2. 一些线程需要在某个时刻同时执行,就像等待裁判员枪响后,才能同时起跑(多个等一个)

此时就不太好控制线程执行的顺序了,需要使用CountDownLatch这个类。

CountDownLatch也是一个同步功能的辅助类,使用效果是给定一个计数,当使用这个CountDownLatch类的线程判断计数不为0时,则呈wait状态,如果为0时则继续运行。实现等待与继续运行的效果分别需要使用await()和countDown()方法来进行。调用await()方法时判断计数是否为0,如果不为0则呈等待状态。其他线程可以调用count-Down()方法将计数减1,当计数减到为0时,呈等待的线程继续运行。而方法getCount()就是获得当前的计数个数。

使用场景

  1. 例子一(一个等多个)

    假如你是学校实验楼的锁门大爷,每天晚上11点之后,实验楼是要锁门的,你就得在所有学生都出来之后才能锁门,每个学生出来都是一个线程(每个学生出来的时间都不一样),而你锁门就是这个最后执行的线程,必须等他们都出来之后才能锁门。

    public static void main(String[] args) throws Exception {
    
    
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
        CountDownLatch countDownLatch = new CountDownLatch(3);
        System.out.println("晚上11点,学校实验室就要关门了,门外李大爷要等学生都出来后才能锁门");
        for (int i = 1; i <= 3; i++) {
    
    
            new Thread(() -> {
    
    
                try {
    
    
                    TimeUnit.SECONDS.sleep(new Random().nextInt(3));
                    System.out.println(Thread.currentThread().getName() + "号学生离开实验室了==="+sdf.format(new Date()));
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }

        countDownLatch.await();
        System.out.println("你们终于都离开了,我要锁门了");
    }
    }

执行结果
在这里插入图片描述

  1. 例子二(多个等一个)

    假如你上学期就顾着打游戏而没有学习的话,那么你肯定是挂科了,然后你就需要补考了,补考的考生一个个的进了教室后,等人都到齐了,监考老师才开始发卷子,然后开始考试,这个过程很重要,每个考生都是一个线程,都有一个任务要处理(那就是考试),但是这个任务硬生生被分成了2部分,一部分进入教室,等待监考老师发卷子,然后等监考老师这个线程执行完任务(发卷子)后,考生才能开始考试,这就是个多个等一个问题。

    public static void main(String[] args) throws Exception {
    
    
        CountDownLatch countDownLatch = new CountDownLatch(1);
        System.out.println("今天上午挂科的需要补考");
        for (int i = 1; i <= 10; i++) {
    
    
            new Thread(() -> {
    
    
                try {
    
    
                    System.out.println(Thread.currentThread().getName() + "号学生进入考场了");
                    countDownLatch.await();
                    System.out.println(Thread.currentThread().getName() + "号学生开始考试了");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }, String.valueOf(i)).start();
        }

        TimeUnit.SECONDS.sleep(1);
        System.out.println("全部考生已经就位,坐等监考老师到来");
        System.out.println("老师进入考场了,开始发卷子了");
        countDownLatch.countDown();
    }

执行结果如下
在这里插入图片描述

总结

CountDownLatch countDownLatch = new CountDownLatch(3);

CountDownLatch初始值里的数字就是一个计数器,每次调用countDown()方法,就会减1,一直减到0为止,一旦减到0的时候,凡是阻塞在CountDownLatch的await()方法上的线程都会被唤醒,继续执行下去。但是CountDownLatch 的计数无法被重置,如果需要重置计数,请考虑使用CyclicBarrier类。

猜你喜欢

转载自blog.csdn.net/csdn_lsby/article/details/109096623
今日推荐