java.util.concurrent包——CountDownLatch使用详解

    xiaoxiao2022-07-02  99

     概念介绍:

    CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值; 每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行; CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件;利用这种特性,可以让主线程等待子线程的结束。

    方法介绍: 

     * 该类主要方法有3个:  * public CountDownLatch(int count)  构造方法参数指定了计数的次数  * public void countDown()  :当前线程调用此方法,则计数减一(任务B调用)  * public void await() throws InterruptedException  :调用此方法会一直阻塞当前线程,直到计时器的值为0(任务A调用)

    使用讲解: 

    要求:有一个任务A想要往下执行,但必须要等到任务B执行完毕后才可以继续往下执行。  * 让任务A调用CountDownLatch对象的await()方法,  * 任务B执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,  * 这个调用await()方法的任务A将一直阻塞等待  * 直到这个CountDownLatch对象的计数值减到0为止,即任务B执行完毕。

     实例讲解:

    题目:假设某公司需召开一个视频会议,共有10名高管参会,只有所有高管均到场后会试才开始。请使用CountDownLatch(包: java.util.concurrent)编写一个示例模 拟上述情景。

    分析:对应到当前题目,任务A:开启视频会议                任务B:10位高管到齐

     代码实现:

    package xmcc.mp_apidemo.test; import java.util.concurrent.CountDownLatch; //任务A的线程,一个线程做一个任务 public class Meet implements Runnable{ //提供一个CountDownLatch对象,用来保证任务A和任务B使用的对象是同一个。 private final CountDownLatch controller; //有参构造,初始化CountDownLatch对象 public Meet(int number) { //初始化计数器为10,因为有10个高管 controller = new CountDownLatch(number); } //提供一个方法:即任务B的具体实现,某一个高管到达 public void arrive(String name) { System.out.println(name + " 到达会议室"); //每达到一位高管,计数器 减1 controller.countDown(); } /** * Runnable是一个线程类,java中常用线程之一 * 使用方法:实现Runnable接口,重写它的run()方法 * 在run()方法里,写线程需要执行的方法。 * 在其他实体类中,start()开启该线程,就会执行run()方法 */ //这个线程实现-》开始会议,即任务A,只要去调用CountDownLatch对象的await()方法即可。 @Override public void run() { System.out.println("会议开启需要 : " + controller.getCount() + " 名高管"); try { controller.await(); System.out.println("所有高管到达会议"); System.out.println("会议开始"); } catch (InterruptedException e) { e.printStackTrace(); } } } //任务B的线程 class Participant implements Runnable{ //之所以需要注入Meet对象,是为了保证两个任务使用的CountDownLatch对象是同一个。 private Meet conference; private String name; public Participant(Meet conference, String name) { this.conference = conference; this.name = name; } //该线程用于--》任务B的具体实现 @Override public void run() { try { Thread.sleep(50);//线程休眠 //某一个高管达到会议室,去调用对应的方法,计数器的值 -1 conference.arrive(name); }catch (InterruptedException e){ e.printStackTrace(); } } //主函数,用于任务A、B的整合 public static void main(String[] args) { //创建任务A的对象,并利用其有参构造,初始化CountDownLatch对象,赋值 定时器的值为10 Meet conference = new Meet(10); //开启任务A的线程,根据CountDownLatch对象await()的属性,任务A需要等待任务B执行完毕(即计数器的值=0的时候) new Thread(conference).start(); //有10位高管,循环开启10个线程,去模拟高管的到场 for(int i=0;i<10;i++) { //创建任务B的对象,10个高管,每次创建一个,模拟某一个高管的到场 Participant p = new Participant(conference, "高管 " + i); //开启任务B的线程,执行对应的run()方法,计算器 -1 new Thread(p).start(); } } }

    运行结果展示:

    会议开启需要 : 10 名高管 高管 0 到达会议室 高管 9 到达会议室 高管 6 到达会议室 高管 7 到达会议室 高管 8 到达会议室 高管 5 到达会议室 高管 3 到达会议室 高管 4 到达会议室 高管 2 到达会议室 高管 1 到达会议室 所有高管到达会议 会议开始

    最新回复(0)