CountDownLatch:并发流程控制工具;倒数门闩;
    例子:购物拼团;游乐园坐过山车排队,人满发车;
    流程:倒数结束之前,一直处于等待状态,直到倒计时结束了,此线程才继续工作

    主要方法介绍:
    CountDownLatch(int count):仅有一个构造函数,参数count为需要倒数的数值
    await():调用wait()方法的线程会被挂起,它会等待直到count值为0才继续执行
    countDown():将count值减1,直到为0时,等待的线程会被唤起

    两个典型用法:多等一和一等多 两者结合
    用法一: 一个线程等待多个线程都执行完毕,再继续自己的工作; 例子:工厂5个质检员,只有都认为该产品合格,才能通过
    用法二:多个线程等待某一个线程的信号,同时开始执行; 例子:跑步运动员等待发令员统一起跑

    注意点:
    扩展用法:多个线程等多个线程完成执行后,再同时执行
    CountDownLatch是不能够重用的,如果需要重新计时,可以考虑使用CycliBarrier或者创建新的CountDownLatch实例

    1. // 倒数门闩演示:工厂中,质检,5个工人检查,所有人都认为通过,才通过;
    2. public class CountDownLatchDemo1 {
    3. public static void main(String[] args) throws InterruptedException {
    4. CountDownLatch latch = new CountDownLatch(5);
    5. ExecutorService service = Executors.newFixedThreadPool(5);
    6. for (int i = 0; i < 5; i++) {
    7. final int finalI = i;
    8. Runnable runnable = new Runnable() {
    9. @Override
    10. public void run() {
    11. try {
    12. Thread.sleep((long) (Math.random()*10000));
    13. System.out.println("No."+ finalI +"完成了检查");
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }finally {
    17. latch.countDown();
    18. }
    19. }
    20. };
    21. service.submit(runnable);
    22. }
    23. System.out.println("5个工人检查中。。。。。。");
    24. latch.await();
    25. System.out.println("工人检查完毕!!!!!!");
    26. service.shutdown();
    27. }
    28. }
    // 模拟百米跑步,5名选手,只等裁判员一声令下,所有人同时跑步;
    // 综合1和2  多等一及一等多情景:5名选手,只等裁判员一声令下,所有人同时跑步;然后等5个运动员都到达终点,就打印所有人到达终点,比赛结束
    public class CountDownLatchDemo1And2 {
        public static void main(String[] args) throws InterruptedException {
            // count 真正的含义是 有几个人倒数,因为裁判员只有一个,所以只有一个倒数
            CountDownLatch begin = new CountDownLatch(1);
            CountDownLatch end = new CountDownLatch(5);
            ExecutorService service = Executors.newFixedThreadPool(5);
            for (int i = 0; i < 5; i++) {
                final int finalI = i + 1;
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        try {
                            System.out.println("No." + finalI + "准备完毕,等待发令枪");
                            begin.await();
                            System.out.println("No." + finalI + "开始跑步了");
                            Thread.sleep((long) (Math.random() * 10000));
                            System.out.println("No." + finalI + "跑到终点");
    
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } finally {
                            end.countDown();
                        }
                    }
                };
                service.submit(runnable);
            }
    
            // 裁判员检查发令枪。。。
            Thread.sleep(3000);
            System.out.println("发令枪响,比赛开始");
            begin.countDown();
    
            end.await();
            System.out.println("所有人到达终点,比赛结束");
    
            service.shutdown();
    
        }
    }