路漫漫其修遠(yuǎn)兮,吾將上下而求索?!峨x騷》
閉鎖
閉鎖(latch)是一種 Synchronizer,他可以延遲線程的進(jìn)度直到線程到達(dá)終止?fàn)顟B(tài)。
一個閉鎖工作起來就像一道大門:直到閉鎖達(dá)到終點(diǎn)狀態(tài)之前,門一直是關(guān)閉的,沒有線程通過,在終點(diǎn)狀態(tài)到來的時(shí)候,門開了,允許所有線程都通過。一旦閉鎖到達(dá)了終點(diǎn)狀態(tài),他就不能夠在改變狀態(tài)了,所以它會永遠(yuǎn)保持敞開的狀態(tài)。
閉鎖的應(yīng)用
- 確保一個計(jì)算不會執(zhí)行,直到它需要的資源被初始化。
- 確保一個服務(wù)不會開始,直到它依賴的服務(wù)都已經(jīng)開始。
- 等待直到活動的所有部分都為繼續(xù)處理做好準(zhǔn)備。比如王者榮耀需要等待所有玩家準(zhǔn)備才能開始。
閉鎖的實(shí)現(xiàn)
CountDownLatch 是一個靈活的閉鎖實(shí)現(xiàn),可以用于上述幾種情況,允許一個或者多個線程等待一個事件集的發(fā)生。閉鎖的狀態(tài)包括一個計(jì)數(shù)器,初始為一個正數(shù),表示要等待的事件數(shù)。countDown方法對于計(jì)數(shù)器做減數(shù)操作,表示一個事件已經(jīng)發(fā)生了,而 await阻塞方法將阻塞當(dāng)前線程直到計(jì)數(shù)器減到零。
CountDownLatch示例
下面舉個例子,CountDownLatchTest 創(chuàng)建兩個特閉鎖對象。第一個是主線程用于判斷所有線程啟動完畢的閉鎖,用于阻塞子線程執(zhí)行直到所有線程都啟動完畢。第二個是子線程執(zhí)行完畢的閉鎖,直到每個線程都執(zhí)行完畢后,才統(tǒng)計(jì)總共運(yùn)行了多少時(shí)間。
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) {
//創(chuàng)建五個線程并啟動
for(int i = 0; i < 5; i++) {
new Thread(new SubThread()).start();
}
long start = System.nanoTime();
main_cdl.countDown();//打開閉鎖,讓五個線程繼續(xù)執(zhí)行
try {
sub_cdl.await();//阻塞閉鎖,等待五個線程都執(zhí)行完畢
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.nanoTime();
System.out.println(end - start);//五個線程總共執(zhí)行了多長時(shí)間
}
//子線程
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();//子線程執(zhí)行完畢,計(jì)數(shù)器減1
}
}
}
}
執(zhí)行結(jié)果:
這里寫圖片描述
本文到此結(jié)束,我們已經(jīng)直到如何去使用閉鎖,和它使用的場景啦。
希望對你有幫助,歡迎關(guān)注我!謝謝~