CountdownLatch 和 CycliBarriar 有什么區(qū)別?
一位工作5年的小伙伴面試的時候,被問到這樣一個問題,說,CountdownLatch 和 CycliBarriar 有什么區(qū)別?這個對于很多人都會比較陌生,但是接觸過并發(fā)編程的小伙伴來說還是比較簡單的。
今天呢,我給大家分享一下我對這個問題的理解。
1、CountdownLatch
先來看CountDownLatch,它是一個組合詞。CountDown 的意思是 倒計時,Latch 的意思是 門閂 ,也被翻譯成發(fā)令槍。在JDK 注釋中是這樣的:
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes。
翻譯過來就是說,讓一個或多個線程持續(xù)等待,直到其他多線程執(zhí)行的一組操作全部完成以后,這些等待的線程才會繼續(xù)執(zhí)行。
就好比是,有多位選手參加一場百米賽跑,裁判員需要等待全部選手就緒,并且在同一起跑線上。然后,裁判會發(fā)出號令:“各就位,預(yù)備跑”,隨著發(fā)令槍響,所有選手才能全部起跑。在這個場景中,各位參賽選手就是線程,而裁判就是CountDownLatch。
我們在實際開發(fā)中,有以下兩個使用場景可以用CountDownLatch來實現(xiàn):
(1)讓單個線程等待多個線程的場景。
比如,一個服務(wù)需要從多個遠程接口獲取數(shù)據(jù),我們可以創(chuàng)建多個線程來分別調(diào)用遠程接口,等待所有遠程接口都獲得返回數(shù)據(jù)之后,主服務(wù)線程再往下繼續(xù)執(zhí)行。像并發(fā)計算,結(jié)果匯總等等。
(2)讓多個線程等待的場景。
比如,模擬秒殺場景,讓一組線程同時等待,同時恢復(fù)執(zhí)行,實現(xiàn)最大程度的并行性。
需要注意的是,當(dāng)高并發(fā)請求時,Countdownlatch的await方法有可能會引起死鎖。
如果線程池中線程的數(shù)量較少,在高并發(fā)時會出現(xiàn)多個請求占用了全部的線程,但是每個請求又需要await()其他線程,被等待的線程拿不到線程資源無法執(zhí)行,導(dǎo)致多個請求同時進入線程阻塞,最后形成死鎖。
當(dāng)然,我們可以使用自定義線程池來擴大線程數(shù)量,并且建立線程池拒絕機制來解決死鎖問題。
2、CyclicBarrier
再來看 CyclicBarrier [?sa?kl?k] [?b?ri?],它也是一個組合詞。其中Cyclic 的意思是 循環(huán) ,Barrier 的意思是 屏障 ,又被翻譯成柵欄。在JDK 注釋中是這樣描述的:
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other.
The barrier is called cyclic because it can be re-used after the waiting threads are released.
翻譯過來總結(jié)為以下三點:
- CyclicBarrier 是一個同步輔助類,它允許一組線程相互等待直到所有線程都到達一個公共的屏障點。
- 在程序中有固定數(shù)量的線程,這些線程有時候必須等待彼此,這種情況下,使用 CyclicBarrier 很有幫助。
- 這個屏障之所以用循環(huán)修飾,是因為在所有的線程釋放彼此之后,這個屏障可以重復(fù)使用。
從字面上理解的話,它的功能和CountdownLatch非常類似,也是等待所有參加比賽的選手全部就緒以后,才能開始起跑。它是另外一種多線程并發(fā)控制工具,和CountdownLatch不同的是,CyclicBarrier可以重復(fù)使用。
我們在實際開發(fā)中,CyclicBarrier可以用于多線程計算數(shù)據(jù),最后合并計算結(jié)果的應(yīng)用場景。
比如,需要計算N組人一年的平均工資,每組需要多個線程并行計算,計算完一組,再開始下一組,這樣就需要多輪并行計算。這個場景下,CyclicBarrier 比 CountDownLatch 更適合。
3、兩者區(qū)別
最后,總結(jié)一下CountDownLatch和CyclicBarrier的區(qū)別,從以下四個方面來分析:
- CountDownLatch的計數(shù)器只能使用一次。而CyclicBarrier的計數(shù)器可以使用reset() 方法重置。
- CyclicBarrier能處理更為復(fù)雜的業(yè)務(wù)場景,比如計算發(fā)生錯誤,可以結(jié)束阻塞,重置計數(shù)器,重新執(zhí)行程序
- CyclicBarrier提供getNumberWaiting()方法,可以獲得CyclicBarrier阻塞的線程數(shù)量,還提供isBroken()方法,可以判斷阻塞的線程是否被中斷,等等。
- CountDownLatch會阻塞主線程,CyclicBarrier不會阻塞主線程,只會阻塞子線程。
好了,以上就是我對CountdownLatch 和 CycliBarriar的理解。