網(wǎng)上有很多文章都討論了CountDownLatch和CyclicBarrier的應(yīng)用場景崔梗,但是大部分CyclicBarrier的應(yīng)用場景都跟實際情況相去甚遠谅猾。
先來看看CountDownLatch:
CountDown 的意思是 倒計時昆汹,Latch 的意思是 門閂 。
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í)行赏枚。
CountDownLatch的使用場景:
1. 讓單個線程等待多個線程
例如:一個服務(wù)需要從3個遠程接口獲取數(shù)據(jù),就可以開三個線程并調(diào)用遠程接口晓猛,等待所有遠程接口數(shù)據(jù)返回之后饿幅,服務(wù)線程再繼續(xù)執(zhí)行。
在比如:并發(fā)計算戒职,匯總結(jié)果栗恩。
2. 讓多個線程等待
例如:模擬秒殺場景,讓一組線程同時等待洪燥,同時恢復(fù)執(zhí)行磕秤,實現(xiàn)最大程度的并行性。
注意:當高并發(fā)請求時蚓曼,countdownlatch的await方法有可能會引起死鎖亲澡。
如果線程池中線程的數(shù)量較少,在高并發(fā)時會出現(xiàn)多個請求占用了全部的線程纫版,但是每個請求又需要await其他線程床绪,被等待的線程拿不到線程資源無法執(zhí)行,導(dǎo)致多個請求同時進入線程阻塞,最后形成死鎖癞己。
解決方法:使用自定義線程池膀斋,擴大線程數(shù)量,并且建立線程池拒絕機制痹雅。
再來看看 CyclicBarrier
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.
- CyclicBarrier 是一個同步輔助類绩社,它允許一組線程相互等待直到所有線程都到達一個公共的屏障點摔蓝。
- 在程序中有固定數(shù)量的線程,這些線程有時候必須等待彼此愉耙,這種情況下贮尉,使用 CyclicBarrier 很有幫助。
- 這個屏障之所以用循環(huán)修飾朴沿,是因為在所有的線程釋放彼此之后猜谚,這個屏障是可以重新使用的。
CyclicBarrier的應(yīng)用場景:
生活中我們會約朋友們到某個餐廳一起吃飯赌渣,有些朋友可能會早到魏铅,有些朋友可能會晚到,但是餐廳規(guī)定必須等到所有人到齊之后才會上菜坚芜。這里的朋友們就是各個線程览芳,餐廳就是 CyclicBarrier。
- 這樣的例子有助于理解CyclicBarrier鸿竖,但我相信開發(fā)中一定不會遇到這樣的場景路操。
CyclicBarrier可以用于多線程計算數(shù)據(jù),最后合并計算結(jié)果的應(yīng)用場景千贯。比如現(xiàn)在需要計算10個人12個月的工資屯仗,可以開10個worker線程,分別計算每個人的工資搔谴,最后魁袜,再用barrierAction將這些線程的計算結(jié)果進行整合,得出最后結(jié)果敦第。
- barrierAction不需要在主線程中執(zhí)行峰弹,這是CyclicBarrier的優(yōu)勢,但是其代價是阻塞了所有的worker線程芜果。
- worker線程計算完成之后鞠呈,把結(jié)果保存就可以釋放線程了,用了CyclicBarrier把線程都阻塞了右钾,然后統(tǒng)一釋放蚁吝,這是什么設(shè)計旱爆?
CyclicBarrier強調(diào)線程之間相互等待
受經(jīng)驗所限,在實際開發(fā)中窘茁,我還沒有需要需要線程相互等待的例子怀伦,而且這樣的場景特別容易造成死鎖。
CyclicBarrier強調(diào)循環(huán)
多輪并行計算:如果需要計算N組人一年的平均工資山林,每組需要多個線程并行計算房待,計算完一組,再開始下一組驼抹,這樣就需要多輪并行計算桑孩。CyclicBarrier 比 CountDownLatch 更適合這樣的場景。
CountDownLatch與CyclicBarrier的區(qū)別:
- CountDownLatch的計數(shù)器只能使用一次框冀。而CyclicBarrier的計數(shù)器可以使用reset() 方法重置
- CyclicBarrier能處理更為復(fù)雜的業(yè)務(wù)場景洼怔,比如計算發(fā)生錯誤,可以結(jié)束阻塞左驾,重置計數(shù)器,重新執(zhí)行程序
- CyclicBarrier還提供getNumberWaiting(可以獲得CyclicBarrier阻塞的線程數(shù)量)极谊、isBroken(用來知道阻塞的線程是否被中斷)等方法
- CountDownLatch會阻塞主線程诡右,CyclicBarrier不會阻塞主線程,只會阻塞子線程