美文网首页多线程JAVA并发java-并发编程
Java并发之CountDownLatch(等待多个并发事件的完

Java并发之CountDownLatch(等待多个并发事件的完

作者: 六尺帐篷 | 来源:发表于2017-07-23 16:00 被阅读366次
    • 引入CountDownLatch类
    • CountDownLatch类的具体实例
    • CountDownLatch小结

    引入CountDownLatch类

    Java在JDK1.5之后引入了CountDownLatch类。这个类是一个同步辅助类。用于一个线程等待多个操作完成之后再执行,也就是这个当前线程会一直阻塞,直到它所等待的多个操作已经完成。首先CountDownLatch类会初始化,设置它需要等待完成的操作的数量。然后每当一个操作完成之后,就会调用countDown方法,这个方法会将CountDownLatch内部的计数器减一。当减为0的时候,CountDownLatch类会唤醒所有调用await方法而进入休眠的线程。

    CountDownLatch类的具体实例

    多说无意,我们具体看一个实例就可以理解CountDownLatch类的使用了。

    我们举一个最直观的例子,比如我们需要开一个视频会议,这个会议需要等待一定的人数到达之后,才开始会议。这种情况就非常适合使用CountDownLatch类来进行同步,也就是等待多个并发事件的发生,因为每个参会人员的到达是并发的。

    首先我们实现会议类,这个类持有一个CountDownLatch类的对象,并且定义了一个arrive方法,每当会议人员到达之后,就会调用这个方法,告诉会议已经到达了,这个方法,会调用CountDown方法,将计数器减一。

    在会议类的run方法中,在宣布会议开始之前,会调用CountDownLatch类的await方法休眠,直到countDown减为0,也就是计数器减为0,说明所有的人都到了,才唤醒继续这个线程的代码,宣布会议开始

    package CountDown;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    public class VideoConference implements Runnable  {
        
        private final CountDownLatch controller;
        
        public VideoConference(int number) {
            controller = new CountDownLatch(10);
        }
        
        public synchronized void arrive(String name) {
            
            
            System.out.println(name + " has arrived.");
            
            System.out.println("VideoConference : waiting for " + (controller.getCount() - 1) + " partivipants");
            
            
            controller.countDown();
        }
        
        @Override
        public void run() {
            System.out.println("VideoConference : Innitiaization : " + controller.getCount() + " participants");
            
            try {
                controller.await();
                System.out.println("All people has come");
                System.out.println("Let's start...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    }
    

    接着我们实现参会人员的类,这个类也实现了runnable接口,首先它持有一个会议对象,为了在执行的时候调用arrive方法,告诉会议人员到了。

    package CountDown;
    
    import java.util.concurrent.TimeUnit;
    
    public class Participant implements Runnable {
    
        private VideoConference conference;
        
        private String name;
        
        public Participant(VideoConference conference, String name) {
            this.conference = conference;
            this.name = name;
        }
        
        
        @Override
        public void run() {
            long duration = (long)Math.random() * 10;
            
            try {
                TimeUnit.SECONDS.sleep(duration + 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            conference.arrive(name);
        }
    
    }
    
    

    最后我们实现测试类

    package CountDown;
    
    public class Main {
    
        public static void main(String[] args) {
            
            VideoConference conference = new VideoConference(10);
            
            new Thread(conference).start();
            
            for(int i=0;i<10;i++) {
                Participant p = new Participant(conference, "Participant " + i);
                new Thread(p).start();
            }
        }
    }
    
    

    运行结果:

    image.png

    await方法还可以指定休眠的时间,当休眠时间到了或者计数器减为0,就会唤醒所有被CountDownLatch休眠的线程,那我们在这里就可以使用这个休眠时间来设置,我们只等10s中,如果10s中,还有人没到,我们也不管了,先开始会议。

    只需对run方法进行简单的修改:

    @Override
        public void run() {
            System.out.println("VideoConference : Innitiaization : " + controller.getCount() + " participants");
            
            try {
                controller.await(10, TimeUnit.SECONDS);
                if(controller.getCount() == 0) {
                    System.out.println("All people has come");
                    System.out.println("Let's start...");
                }
                else {
                    System.out.println("不等了");
                    System.out.println("Let's start...");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    

    运行结果

    image.png

    CountDownLatch小结

    CountDownLatch有三个基本的要素:

    • 一个初始值,定义必须等待多少个并发线程完成的数目

    • await方法,需要等到其他操作先完成的那个线程调用的,先将线程休眠,直到其他操作完成,计数器减为0,才会唤醒因此休眠的线程

    • countDown方法,每个被等待的事件在完成之后调用,会将计数器减一

    • CountDownLatch不是用来保护临界区和共享资源的,是用来同步执行线程和操作的

    • CountDownLatch是一次性的,当计数器减为0 之后,这个类就相当于没用,我们之后对它的操作都不起作用,需要新建一个countDownLatch类

    相关文章

      网友评论

        本文标题:Java并发之CountDownLatch(等待多个并发事件的完

        本文链接:https://www.haomeiwen.com/subject/pqdmkxtx.html