java并发笔记之--CountDownLatch

作者: a77118d36d9b | 来源:发表于2017-11-08 19:59 被阅读122次
    java并发笔记之--CountDownLatch

    java并发笔记之--CountDownLatch

    decodelife

    知乎 decodelife转载请注明出处

    本文为java并发笔记系列之--- CountDownLatch

    概念

    单词Latch,中文翻译是门闩,也就是有“门锁”的功能,所以当门没有打开时,N个人是不能进入屋内的,也就是N个线程是不能继续向下运行的,支持这样的特性可以控制线程执行任务的时机,使线程以“组团”的方式一起执行任务。

    类CountDownLatch也是一个同步功能的辅助类,使用效果是给定一个计数,当使用这个CountDownLatch类的线程判断计数不为0时,则呈wait状态,如果为0时则继续运行

    使用场景

    接下来借助百米短跑场景进行讲解使用场景。

    1. 首先裁判需要等待所有的运动员到场
    2. 然后运动员等待裁判发起准备信号
    3. 裁判等待所有运动员准备就绪,裁判发起起跑信号
    4. 裁判等待运动员全部跑完
    5. 裁判宣布比赛结束

    实现代码如下所示

    package com.shunwang.swbox.show.service;
    
    import java.util.concurrent.CountDownLatch;
    
    /**
     * 短跑运动员
     *
     * @author ljs.song
     * @date 2017-11-08 19:08
     */
    public class RunerPepole extends Thread{
    
        //运动员达起点过程
        private CountDownLatch comingTag;
        //运动员等待裁判准备信号
        private CountDownLatch waitTag;
        //运动员等待裁判起跑信号
        private CountDownLatch waitRunTag;
        //运动员等待裁判说起跑
        private CountDownLatch beginTag;
        //运动员到达终点
        private CountDownLatch endTag;
    
        public RunerPepole(CountDownLatch comingTag, CountDownLatch waitTag, CountDownLatch waitRunTag, CountDownLatch beginTag, CountDownLatch endTag) {
            super();
            this.comingTag = comingTag;
            this.waitTag = waitTag;
            this.waitRunTag = waitRunTag;
            this.beginTag = beginTag;
            this.endTag = endTag;
        }
    
        @Override
        public void run() {
            System.out.println("运动员"+Thread.currentThread().getName() + "正在骑车赶到起点");
            try {
                Thread.sleep(2000);
                System.out.println("运动员"+Thread.currentThread().getName() + "到达起点,等待准备");
                comingTag.countDown();
    
                waitTag.await();
    
                System.out.println("运动员"+Thread.currentThread().getName() + "正在准备……");
                Thread.sleep(1000);
    
                waitRunTag.countDown();
    
                //等待裁判起跑信号
                beginTag.await();
    
                System.out.println("运动员"+Thread.currentThread().getName() + "到达终点******");
                endTag.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 裁判端
         * @param args
         */
        public static void main(String[] args) {
            CountDownLatch comintTag = new CountDownLatch(10);
            CountDownLatch waitTag = new CountDownLatch(1);
            CountDownLatch waitRunTag = new CountDownLatch(10);
            CountDownLatch beginTag = new CountDownLatch(1);
            CountDownLatch endTag = new CountDownLatch(10);
    
            RunerPepole[] runerPepoles = new RunerPepole[10];
            for (int i = 0; i < 10; i++) {
                runerPepoles[i] = new RunerPepole(comintTag, waitTag, waitRunTag, beginTag, endTag);
                runerPepoles[i].start();
            }
    
            try {
                System.out.println("裁判等待所有运动员到场");
                comintTag.await();
    
                //裁判发起准备信号
                System.out.println("裁判发起准备信号");
                waitTag.countDown();
    
                System.out.println("裁判检查等待所有人准备完成");
                waitRunTag.await();
    
                System.out.println("裁判发起起跑信号--------------");
                beginTag.countDown();
    
                endTag.await();
                System.out.println("所有运动员到达终点,比赛结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    运行结果

    运动员Thread-0正在骑车赶到起点
    运动员Thread-4正在骑车赶到起点
    运动员Thread-2正在骑车赶到起点
    运动员Thread-6正在骑车赶到起点
    运动员Thread-1正在骑车赶到起点
    裁判等待所有运动员到场
    运动员Thread-3正在骑车赶到起点
    运动员Thread-5正在骑车赶到起点
    运动员Thread-7正在骑车赶到起点
    运动员Thread-9正在骑车赶到起点
    运动员Thread-8正在骑车赶到起点
    运动员Thread-1到达起点,等待准备
    运动员Thread-5到达起点,等待准备
    运动员Thread-9到达起点,等待准备
    运动员Thread-4到达起点,等待准备
    运动员Thread-8到达起点,等待准备
    运动员Thread-0到达起点,等待准备
    运动员Thread-3到达起点,等待准备
    运动员Thread-6到达起点,等待准备
    运动员Thread-2到达起点,等待准备
    运动员Thread-7到达起点,等待准备
    裁判发起准备信号
    裁判检查等待所有人准备完成
    运动员Thread-1正在准备……
    运动员Thread-5正在准备……
    运动员Thread-9正在准备……
    运动员Thread-4正在准备……
    运动员Thread-8正在准备……
    运动员Thread-0正在准备……
    运动员Thread-3正在准备……
    运动员Thread-6正在准备……
    运动员Thread-2正在准备……
    运动员Thread-7正在准备……
    裁判发起起跑信号--------------
    运动员Thread-1到达终点******
    运动员Thread-5到达终点******
    运动员Thread-9到达终点******
    运动员Thread-4到达终点******
    运动员Thread-8到达终点******
    运动员Thread-0到达终点******
    运动员Thread-7到达终点******
    运动员Thread-3到达终点******
    运动员Thread-6到达终点******
    运动员Thread-2到达终点******
    所有运动员到达终点,比赛结束
    
    Process finished with exit code 0
    
    

    如上结果可以看到,所有的10个运动员在每个节点未拿到信号前,都处于等待(阻塞)状态,然后拿到信号后,指定数量的运动员(线程)一起开始运行,这样能达到上述概念中描述的“门锁”的概念,方便我们工作场景中灵活控制

    相关文章

      网友评论

      本文标题:java并发笔记之--CountDownLatch

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