路漫漫其修遠兮,吾將上下而求索。———屈原《離騷》
閉鎖
閉鎖(latch)是一種 Synchronizer,他可以延遲線程的進度直到線程到達終止狀態。
一個閉鎖工作起來就像一道大門:直到閉鎖達到終點狀態之前,門一直是關閉的,沒有線程通過,在終點狀態到來的時候,門開了,允許所有線程都通過。一旦閉鎖到達了終點狀態,他就不能夠在改變狀態了,所以它會永遠保持敞開的狀態。
閉鎖的應用
- 確保一個計算不會執行,直到它需要的資源被初始化。
- 確保一個服務不會開始,直到它依賴的服務都已經開始。
- 等待直到活動的所有部分都爲繼續處理做好準備。比如王者榮耀需要等待所有玩家準備才能開始。
閉鎖的實現
CountDownLatch 是一個靈活的閉鎖實現,可以用於上述幾種情況,允許一個或者多個線程等待一個事件集的發生。閉鎖的狀態包括一個計數器,初始爲一個正數,表示要等待的事件數。countDown方法對於計數器做減數操作,表示一個事件已經發生了,而 await阻塞方法將阻塞當前線程直到計數器減到零。
CountDownLatch示例
下面舉個例子,CountDownLatchTest 創建兩個特閉鎖對象。第一個是主線程用於判斷所有線程啓動完畢的閉鎖,用於阻塞子線程執行直到所有線程都啓動完畢。第二個是子線程執行完畢的閉鎖,直到每個線程都執行完畢後,才統計總共運行了多少時間。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest{
private static CountDownLatch main_cdl = new CountDownLatch(1);//閉鎖1
private static CountDownLatch sub_cdl = new CountDownLatch(5);//閉鎖2
public static void main(String[] args) {
//創建五個線程並啓動
for(int i = 0; i < 5; i++) {
new Thread(new SubThread()).start();
}
long start = System.nanoTime();
main_cdl.countDown();//打開閉鎖,讓五個線程繼續執行
try {
sub_cdl.await();//阻塞閉鎖,等待五個線程都執行完畢
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.nanoTime();
System.out.println(end - start);//五個線程總共執行了多長時間
}
//子線程
static class SubThread implements Runnable{
public SubThread() {}
@Override
public void run() {
try {
main_cdl.await();//阻塞,等待主線程啓動所有子線程你
System.out.println(Thread.currentThread().getName() + ":runing");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
sub_cdl.countDown();//子線程執行完畢,計數器減1
}
}
}
}
執行結果:
本文到此結束,我們已經直到如何去使用閉鎖,和它使用的場景啦。
希望對你有幫助,歡迎關注我!謝謝~
本文原創首發於微信公衆號 [ 林裏少年 ],歡迎關注第一時間獲取更新。