CountDownLatch--等待多線程計數器

一、概述

CountDownLatch是什麼?網上概念的描述太多了。其實個人理解,他就是--等待多線程計數器

即:在某線程中(主線程或其他分線程都可以)聲明一個初始值爲N的CountDownLatch計數器,然後等待多個子線程完成了相關操作後再繼續向下執行。--當各子線程執行到相應的地方後使N-1,最後N=0時,線程不再等待,繼續向下執行。

 

二、運用及場景

2.1、運用

  1. CountDownLatch latch = new CountDownLatch(N); //構造對象時候 需要傳入參數N  即計數器值
  2. latch.await();//能夠阻塞線程 直到調用N次latch.countDown() 方法才釋放線程
  3. latch.countDown();//在多個子線程中調用 每次調用,N計數器值-1

2.2、場景

需要等待其他線程做完某動作後再繼續執行後續操作(當前線程多異步操作完成後再向下執行)--或等待超時後繼續執行。
例:每天0點同時備份前一天的數據表,即0點開啓與備份表相同的線程數分別同時備份表,全部成功後返回true,失敗後返回false

 

 

三、案例解析

3.1、描述一個案例:3個人在等公交,公交停下後,分別上車,找到座位後車才啓動。

先創建一個值爲3(nameList.length)的CountDownLatch計數器 → 啓動3個子線程分別執行任務(之後,主線程陷入等待latch.await()) → 子線程執行後將計數器-1(latch.countDown()) → 計數器值爲0後喚醒主線程繼續向下執行

public static void main(String[] args) {
    try {
        Random random = new Random();//生成隨機數類
	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式
	System.out.println("現在是北京時間:"+df.format(new Date())+"======>公交車停車了!");
		 
	String[] nameList = new String[]{"張三","李四","王五"};//假設此爲在公交站臺排隊的人
	CountDownLatch latch = new CountDownLatch(nameList.length);//聲明一個與人數相等的計數器
	for(String name : nameList){
	    new Thread(new Runnable() {
	    @Override
	    public void run() {
	        try {
		    System.out.println(name+"小老弟,上車了!===》"+df.format(new Date()));
		    int s = random.nextInt(6);//生成0-6的隨機數,用做等待秒數
		    System.out.println(name+"小老弟,找座位需要===》"+s+"秒!");
		    Thread.sleep(s*1000);//等待s秒
		    System.out.println(name+"小老弟,找到座位了!===》"+df.format(new Date()));
		} catch (Exception e) {
		    e.printStackTrace();
		} finally {
		    latch.countDown();//計數器-1
		}
	    }
	    }).start();
	}
	latch.await();//等待
	System.out.println("現在是北京時間:"+df.format(new Date())+"======>公交車啓動了!");
    } catch (InterruptedException e) {
	e.printStackTrace();
    }
}

 

結果:

 

3.2、描述一個案例:3個人在等公交,公交停下後分別上車,待2人找到位置後,或2秒之後,公交啓動。

先創建一個值爲2的CountDownLatch計數器 → 啓動3個子線程分別執行任務(之後,主線程陷入等待latch.await(2, TimeUnit.SECONDS),超時時間設置爲2秒) → 子線程執行後將計數器-1(latch.countDown()) → 計數器值爲0或等待超時後 喚醒主線程繼續向下執行

public static void main(String[] args) {
    try {
        Random random = new Random();//生成隨機數類
	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//設置日期格式
	System.out.println("現在是北京時間:"+df.format(new Date())+"======>公交車停車了!");
		 
	String[] nameList = new String[]{"張三","李四","王五"};//假設此爲在公交站臺排隊的人
	CountDownLatch latch = new CountDownLatch(2);//聲明一個與人數相等的計數器
	for(String name : nameList){
	    new Thread(new Runnable() {
	    @Override
	    public void run() {
	        try {
		    System.out.println(name+"小老弟,上車了!===》"+df.format(new Date()));
		    int s = random.nextInt(6);//生成0-6的隨機數,用做等待秒數
		    System.out.println(name+"小老弟,找座位需要===》"+s+"秒!");
		    Thread.sleep(s*1000);//等待s秒
		    System.out.println(name+"小老弟,找到座位了!===》"+df.format(new Date()));
		} catch (Exception e) {
		    e.printStackTrace();
		} finally {
	            latch.countDown();//計數器-1
		}
	    }
	    }).start();
	}
	latch.await(2, TimeUnit.SECONDS);//等待計數器爲0,或2秒
	System.out.println("現在是北京時間:"+df.format(new Date())+"======>公交車啓動了!");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

結果:

可能性1:

可能性2:

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