CyclicBarrier循環(huán)屏障(障礙)笨奠,同樣都是jdk線程并發(fā)包下的java.util.concurrent,底層使用ReentrantLock可重入鎖阀坏,共享資源重復(fù)加鎖到忽,該線程獲取鎖不被阻塞率挣。
使用場景:約好4個人一起打麻將,如果是三缺一就無法進行训堆,三個人需要等待1人描验,四個人達到麻將館即可開戰(zhàn)。
或者處理間斷坑鱼,反復(fù)請求時膘流,避免一條條的處理,定義規(guī)則滿足10次提交一次業(yè)務(wù)流,當不滿足10次呼股,一直阻塞等待耕魄。
/**
* CyclicBarrier 循環(huán)屏障
* jdk:"一種同步幫助,允許一組線程等待所有線程,互相達到一個共同的障礙點",大白話講:滿足n個線程數(shù)量,才能訪問后續(xù)動作彭谁,不滿足就一直等待吸奴。
*/
public class CyclicBarrierTest {
public static final Logger logger = LoggerFactory.getLogger(CyclicBarrierTest.class);
public static void main(String[] args) {
/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and
* does not perform a predefined action when the barrier is tripped.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @throws IllegalArgumentException if {@code parties} is less than 1
*/
//定義5個循環(huán)障礙,5個線程執(zhí)行完后,會解除阻塞马靠,計數(shù)清零奄抽。然后循環(huán)重復(fù)此規(guī)則
CyclicBarrier cyclicBarrier = new CyclicBarrier(5);
//定義一個緩存線程池,如果有空閑的線程進行回收,否則創(chuàng)建新的線程
ExecutorService executors = Executors.newCachedThreadPool();
//這里可以模擬不同的請求數(shù)來驗證甩鳄,第一次可以循環(huán)5次逞度,第二次循環(huán)6次,第三次循環(huán)10次妙啃,來觀察不同之處
//循環(huán)5次档泽,剛好一組任務(wù)完成。
//循環(huán)6次揖赴,只能滿足第一組任務(wù)馆匿,第二組任務(wù)將一直等待,阻塞任務(wù)燥滑。
//循環(huán)十次渐北,兩組任務(wù)都可以完成。
for (int i = 0; i < 10; i++) {
executors.execute(() -> {
logger.info(Thread.currentThread().getName() + "進入考場");
try {
//dowait方法ReentrantLock 可重入鎖
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
logger.info(Thread.currentThread().getName() + "開始考試...");
});
}
executors.shutdown();
}
}
日中輸出:
18:05:19.283 [pool-1-thread-3] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-3進入考場
18:05:19.283 [pool-1-thread-4] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-4進入考場
18:05:19.283 [pool-1-thread-5] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-5進入考場
18:05:19.283 [pool-1-thread-1] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-1進入考場
18:05:19.283 [pool-1-thread-2] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-2進入考場
18:05:19.286 [pool-1-thread-3] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-3開始考試...
18:05:19.286 [pool-1-thread-5] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-5開始考試...
18:05:19.286 [pool-1-thread-4] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-4開始考試...
18:05:19.286 [pool-1-thread-2] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-2開始考試...
18:05:19.286 [pool-1-thread-1] INFO com.test.tenant.CyclicBarrierTest - pool-1-thread-1開始考試...
CyclicBarrier 和CountDownLatch區(qū)別:
阻塞區(qū)別:
CountDownLatch某一個或多個線程 铭拧,等待其他線程執(zhí)行完成之后赃蛛,才能繼續(xù)執(zhí)行。父線程等待子線程執(zhí)行完成搀菩,才能繼續(xù)執(zhí)行呕臂。
CyclicBarrier 一組線程互相等待,任何一個未執(zhí)行完成肪跋,其他線程都需要等待歧蒋。10個線程,全部完成州既,才能執(zhí)行后續(xù)動作谜洽。
使用次數(shù)區(qū)別:
CountDownLatch倒計時門閂,每執(zhí)行一次都是遞減1吴叶,await等于0時褥琐,結(jié)束阻塞,不可重復(fù)使用
CyclicBarrier循環(huán)屏障晤郑,每執(zhí)行一次都是遞加1敌呈,barrier釋放完后贸宏,可繼續(xù)使用,重復(fù)循環(huán)使用磕洪。
鎖區(qū)別
CountDownLatch 內(nèi)部使用 Sync AQS 狀態(tài)來控制吭练,volatile可見性控制線程間變量共享
CyclicBarrier內(nèi)部使用ReentrantLock可重入鎖