CountDownLatch 源碼學習

1、CountDownLatch 的作用

一種同步輔助,允許一個或多個線程等待,直到在其他線程中執行的一組操作完成。

一個通用的同步工具,可以用於多種用途。初始化一個count爲1的 CountDownLatch 作爲一個簡單的on/off閂鎖或門:所有調用 wait 的線程都在門上等待,直到調用 countDown 的線程打開它。一個初始化爲N的 CountDownLatch 可以用來讓一個線程等待,直到N線程完成某個動作,或者某個動作已經完成N次。

2、核心方法

    // 構造函數,使用AQS的 status 屬性實現
    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }
	/**
	 * 
	 * 方法描述:除非當前線程中斷,否則當前線程等待,直到鎖存器計數爲零。
	 * 如果當前計數爲零,則此方法立即返回。
	 * 如果當前線程數大於零,則當前線程將出於線程調度的目的而禁用,並處於休眠狀態,直到發生以下兩種情況之一:
	 * 	1.調用 countDown 方法,計數爲零;
	 * 	2.其他線程中斷當前線程。
	 *
	 */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    // 遞減鎖存器的計數,如果計數爲零,則釋放所有等待的線程。
    // 如果當前計數大於零,則遞減。如果新計數爲零,則重新啓用所有等待線程,以實現線程調度的目的。
    // 如果當前計數爲零,則什麼也不會發生。
    public void countDown() {
        sync.releaseShared(1);
    }

3、實例測試

有一個駕駛員和多個工人,駕駛員準備好以後工人纔可以開始工作,工人全部工作完以後進行整理彙報。

github地址

/**
 * 
 * CountDownLatch用法實例(來自JDK1.8 CountDownLatch)
 * 有一個駕駛員和多個工人,駕駛員準備好以後工人纔可以開始工作,工人全部工作完以後進行整理彙報。
 * 對一組工作線程使用兩個倒計時鎖。
 * 	第一個是一個啓動信號(startSignal),阻止任何工人繼續工作,直到駕駛員準備好繼續行駛。
 * 	第二個信號是完成信號(doneSignal),允許駕駛員等待直到所有工人都完成。
 * 
 * @version 1.0
 */
public class CountDownLatchDriverDemo_01 {

	public static void main(String[] args) throws InterruptedException {
		CountDownLatch startSignal = new CountDownLatch(1);
		CountDownLatch doneSignal = new CountDownLatch(10);
		
		for (int i = 0; i < 10; i++) {
			new Thread(new CountDownLatchWorkerDemo_01(startSignal, doneSignal)).start();
		}
	
		Random random = new Random();
		Integer sleepDrver = random.nextInt(1000);
		Thread.sleep(sleepDrver);
		System.out.println("駕駛員準備了 " + sleepDrver + " 毫秒,已經準備好了。");
		/**
		 * 減少鎖的計數,如果計數爲零,釋放所有線程
		 * 如果註釋掉,線程不會繼續運行
		 */
		startSignal.countDown();			
		System.out.println("工人已經準備好了,開始工作。");
		/**
		 * 使當前線程等待,直到鎖計數爲零
		 * 如果註釋掉,不會等到線程運行完就直接運行後續代碼
		 */
		doneSignal.await();					
		System.out.println("工人工作全部完成。");
	}
	
}

class CountDownLatchWorkerDemo_01 implements Runnable {
	private final CountDownLatch startSignal;
	private final CountDownLatch doneSignal;
	
	CountDownLatchWorkerDemo_01(CountDownLatch startSignal, CountDownLatch doneSignal) {
		this.startSignal = startSignal;
		this.doneSignal = doneSignal;
	}

	public void run() {
		try {
			startSignal.await();
			Random random = new Random();
			Integer sleep = random.nextInt(1000);
			Thread.sleep(sleep);
			System.out.println("工人" + Thread.currentThread().getId() + "開始工作,工作時間 " + sleep + "毫秒,工作完成。");
			doneSignal.countDown();
		} catch (Exception e) {

		}
	}
	
}

 

 

 

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