java併發筆記之--CountDownLatch

1762862-854bd179d7ead91e.png
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);
            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個運動員在每個節點未拿到信號前,都處於等待(阻塞)狀態,然後拿到信號後,指定數量的運動員(線程)一起開始運行,這樣能達到上述概念中描述的“門鎖”的概念,方便我們工作場景中靈活控制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章