CyclicBarrier(循環(huán)屏障) 直譯為可循環(huán)使用(Cyclic)的屏障(Barrier)。它可以讓一組線程到達一個屏障(同步點)時被阻塞,直到最后一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續(xù)工作。
應(yīng)用場景: CyclicBarrier可以用于多線程計算數(shù)據(jù),最后合并計算結(jié)果的應(yīng)用場景。比如現(xiàn)在需要計算10個人12個月內(nèi)的工資詳細,可以將線程分為10個,分別計算每個人的工資,最后,再用barrierAction將這些線程的計算結(jié)果進行整合,得出最后結(jié)果。
CountDownLatch與CyclicBarrier:
CountDownLatch是一個同步的輔助類,允許一個或多個線程,等待其他一組線程完成操作,再繼續(xù)執(zhí)行。
CyclicBarrier是一個同步的輔助類,允許一組線程相互之間等待,達到一個共同點,再繼續(xù)執(zhí)行。
區(qū)別:
CountDownLatch的計數(shù)器只能使用一次。而CyclicBarrier的計數(shù)器可以使用reset() 方法重置。所以CyclicBarrier能處理更為復(fù)雜的業(yè)務(wù)場景,比如如果計算發(fā)生錯誤,可以重置計數(shù)器,并讓線程們重新執(zhí)行一次
CyclicBarrier還提供getNumberWaiting(可以獲得CyclicBarrier阻塞的線程數(shù)量)、isBroken(用來知道阻塞的線程是否被中斷)等方法。
CountDownLatch會阻塞主線程,CyclicBarrier不會阻塞主線程,只會阻塞子線程。
代碼實例:
假設(shè)要分別計算員工1和員工2的工資,并在都計算完之后進行整合操作,代碼實現(xiàn)邏輯如下
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo1 {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
@Override
public void run() {
System.out.println("匯總已分別計算出的兩個員工的工資");
}
});
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("計算出員工1的工資");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "thread1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("計算出員工2的工資");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}, "thread2");
thread1.start();
thread2.start();
System.out.println("CyclicBarrier不會阻塞主線程");
}
}
輸出結(jié)果:
CyclicBarrier不會阻塞主線程
計算出員工1的工資
計算出員工2的工資
匯總已分別計算出的兩個員工的工資