大师网-带你快速走向大师之路 解决你在学习过程中的疑惑,带你快速进入大师之门。节省时间,提升效率

java并发笔记之--CountDownLatch

java并发笔记之--CountDownLatch
java并发笔记之--CountDownLatch

java并发笔记之--CountDownLatch

知乎 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);
            comingTag.countDown();
            System.out.println("运动员"+Thread.currentThread().getName() + "到达起点,等待准备");

            waitTag.await();

            System.out.println("运动员"+Thread.currentThread().getName() + "正在准备……");
            Thread.sleep(1000);

            waitRunTag.countDown();

            //等待裁判起跑信号
            beginTag.await();

            endTag.countDown();
            System.out.println("运动员"+Thread.currentThread().getName() + "到达终点******");
        } 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个运动员在每个节点未拿到信号前,都处于等待(阻塞)状态,然后拿到信号后,指定数量的运动员(线程)一起开始运行,这样能达到上述概念中描述的“门锁”的概念,方便我们工作场景中灵活控制