Java CountDownLatch的使用方法
摘要:介紹Java中CountDownLatch的使用方法,重點(diǎn)包括計(jì)數(shù)器的值、countDown和await。計(jì)數(shù)器的值表示任務(wù)線程的個(gè)數(shù),每次countDown都會(huì)使計(jì)數(shù)減一,減到0的時(shí)候調(diào)用await方法的線程就不再被阻塞。
綜述
??CountDownLatch一般被稱作"計(jì)數(shù)器",計(jì)數(shù)器的初始值是線程的數(shù)量,是一個(gè)同步工具類,用來協(xié)調(diào)多個(gè)線程之間的同步。其中,count down是倒數(shù)的意思,latch則是門閂的含義,整體含義可以理解為倒數(shù)的門栓;有一點(diǎn)“三二一,芝麻開門”的感覺。
??CountDownLatch在初始化時(shí),需要指定一個(gè)正整數(shù)作為計(jì)數(shù)器起始值,每當(dāng)一個(gè)線程執(zhí)行完畢后,計(jì)數(shù)器就被countDown方法減1,當(dāng)計(jì)數(shù)器為0時(shí),表示所有線程都執(zhí)行完畢,然后在閉鎖上等待的線程就被喚醒,恢復(fù)工作。從線程執(zhí)行狀態(tài)的角度分析,就是允許一個(gè)或多個(gè)線程等待,直到其它線程執(zhí)行完成才繼續(xù)往下走。
??CountDownLatch是在java 1.5 被引入的,與它一起被引入的工具類還包括CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue等,它們都位于java.util.cucurrent包下。
??CountDownLatch的計(jì)數(shù)器無法被重置,當(dāng)計(jì)數(shù)器被減到0時(shí),調(diào)用await方法會(huì)直接返回。這一點(diǎn)有別于Semaphore,Semaphore是可以通過release操作恢復(fù)信號(hào)量的。
CountDownLatch類
??CountDownLatch 類提供了三個(gè)核心構(gòu)造器:
//參數(shù)count為計(jì)數(shù)值,即線程個(gè)數(shù)
public CountDownLatch(int count) { };
/**
* Causes the current thread to wait until the latch has counted down to
* zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
*
* <p>If the current count is zero then this method returns immediately.
*
* 調(diào)用await()方法的線程會(huì)被掛起,直到count值為0才繼續(xù)執(zhí)行
*/
public void await() throws InterruptedException { };
//和await()類似,只不過等待一定的時(shí)間后,如果計(jì)數(shù)器的值還沒倒數(shù)至0,就會(huì)被喚醒繼續(xù)執(zhí)行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };
/**
* Decrements the count of the latch, releasing all waiting threads if
* the count reaches zero.
* 每次減少一個(gè)門閂數(shù),如果等于零,則釋放等待線程
* <p>If the current count is greater than zero then it is decremented.
* If the new count is zero then all waiting threads are re-enabled for
* thread scheduling purposes.
*
* <p>If the current count equals zero then nothing happens.
*/
public void countDown() { };
??如果想使線程處于等待狀態(tài),則調(diào)用await()方法,此線程一般是主線程。溫馨提示,await()方法并沒有規(guī)定只能由一個(gè)線程執(zhí)行,如果多個(gè)線程同時(shí)執(zhí)行await()方法,那么這幾個(gè)線程都將處于等待狀態(tài),并且以共享模式享有同一把鎖。另外,當(dāng)同一個(gè)線程多次調(diào)用countDown()方法時(shí),每次都會(huì)使計(jì)數(shù)器減一;
??簡(jiǎn)單總結(jié)一下,CountDownLatch有三個(gè)重點(diǎn):計(jì)數(shù)器的值、await、countDown。計(jì)數(shù)器的值表示任務(wù)線程的個(gè)數(shù),每次countDown都會(huì)使計(jì)數(shù)減一,減到0的時(shí)候await方法所在的線程就不再被阻塞。
使用場(chǎng)景
??CountDownLatch非常適合于對(duì)任務(wù)進(jìn)行拆分,使其并行執(zhí)行,實(shí)現(xiàn)最大的并行性。某一線程A在開始運(yùn)行前一直被阻塞,需等待n個(gè)其它線程執(zhí)行完畢,則需將CountDownLatch的計(jì)數(shù)器初始化為 new CountDownLatch(n),每當(dāng)一個(gè)任務(wù)線程執(zhí)行完畢,則調(diào)用countDown()函數(shù)使得計(jì)數(shù)器減一;當(dāng)計(jì)數(shù)器變?yōu)?時(shí),在CountDownLatch上await()的線程A就會(huì)被喚醒。
??例1,會(huì)計(jì)匯總一年的財(cái)務(wù)報(bào)表時(shí),可以把任務(wù)按照季度拆分為四份,那么就可以將這個(gè)大任務(wù)拆分為4個(gè)子任務(wù),分別交由4個(gè)財(cái)務(wù)(線程)執(zhí)行,執(zhí)行完成之后再由主財(cái)務(wù)(主線程)進(jìn)行財(cái)務(wù)匯總。此時(shí),總的執(zhí)行時(shí)間將決定于執(zhí)行最慢的任務(wù),通常來看,還是可以大大減少總的執(zhí)行時(shí)間。
??例2,有10個(gè)線程需要加載一些資源,而另外一個(gè)線程A必須在所有資源被加載完成后才能繼續(xù)執(zhí)行,那么我們可以new一個(gè)CountDownLatch(10)的閉鎖,每個(gè)加載資源的線程執(zhí)行完后都調(diào)用countDown()函數(shù),而線程A則在需要的資源準(zhǔn)備齊全之前因調(diào)用await函數(shù)而被阻塞,當(dāng)計(jì)數(shù)器的值為0時(shí),線程A就會(huì)被喚醒繼續(xù)執(zhí)行。
知行合一
??案例如下:
結(jié)束語
??JUC CountDownLatch是一個(gè)同步工具類,用來協(xié)調(diào)多個(gè)線程之間的同步。這個(gè)工具通常用來控制線程等待,它可以讓某一個(gè)線程等待直到倒計(jì)時(shí)結(jié)束,再開始執(zhí)行。原理:它通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始化值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后,計(jì)數(shù)器的值就減一。當(dāng)計(jì)數(shù)器遞減至零時(shí),表示所有的線程都已完成任務(wù),然后在閉鎖上等待的線程就被喚醒,恢復(fù)執(zhí)行任務(wù)。
??老鐵們, 因個(gè)人能力有限,難免有瑕疵,如果發(fā)現(xiàn)bug或者有更好的建議,那么請(qǐng)?jiān)谖恼孪路搅粞裕?/p>
Buy me a coffee. ?Get red packets.
浙公網(wǎng)安備 33010602011771號(hào)