CountDownLatch是Java 5新增加的一個併發工具類,可以使一個線程等待其他線程執行完畢後再執行。CountDownLatch是通過一個計數器來實現的,計數器的初始值是線程的數量,每當一個線程執行完畢後,計數器的值就-1,當計數器的值爲0時,表示所有線程都執行完畢,然後被阻塞的線程就可以繼續執行了。CountDownLatch計數器的操作是原子操作,同時只能有一個線程去操作這個計數器。
CountDownLatch是一種共享鎖,就是允許多個線程同時獲取一個鎖,一個鎖可以同時被多個線程擁有。共享鎖(S鎖)又稱讀鎖,若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。
CountDownLatch類的方法如下:
定義 | 描述 |
---|---|
CountDownLatch(int count) | CountDownLatch類初始化,設置計數器的初始值,即需等待的線程數量。 |
void await() | 使一個線程開始等待,直到CountDownLatch計數器的值爲零後,再繼續向下執行。 |
boolean await(long timeout, TimeUnit unit) | 功能同上,但可以設置等待超時時間,超時後返回false,並繼續向下執行。未超時返回true。 |
void countDown() | 線程執行完畢後調用,CountDownLatch計數器的值減1。 |
long getCount() | 獲取當前CountDownLatch計數器的值。 |
CountDownLatch簡單應用示例:
如上圖,主線程調用await()後,除非計數器值爲0,否則會一直阻塞休眠。當所有任務執行完後,主線程被喚醒,繼續向下執行。
共享鎖應用示例:
CountDownLatch類可以在任意多個地方執行await()方法,不同線程也可以,一切只依據狀態值,不受限於任何的場景。如上圖,在線程3和線程4分別調用了await(),當狀態值爲0後,這兩個線程將會繼續執行,但執行順序無法保證。
在Java 5提供的併發包下,有一個AbstractQueuedSynchronizer抽象類,也叫AQS,此類根據大部分併發共性作了一些抽象,便於開發者實現如排他鎖、共享鎖、條件等待等更高級的業務功能,它通過使用CAS和隊列模型完成抽象任務。
當多個線程調用await()時,會按調用順序加入等待喚醒的同步隊列。狀態值爲0後,將以鏈式喚醒機制按加入等待隊列的順序喚醒線程。如下圖: