CyclicBarrier使用
CyclicBarrier迴圈屏障(障礙),同樣都是jdk執行緒併發包下的java.util.concurrent,底層使用ReentrantLock可重入鎖,共享資源重複加鎖,該執行緒獲取鎖不被阻塞。
使用場景:約好4個人一起打麻將,如果是三缺一就無法進行,三個人需要等待1人,四個人達到麻將館即可開戰。
或者處理間斷,反覆請求時,避免一條條的處理,定義規則滿足10次提交一次業務流,當不滿足10次,一直阻塞等待。
/** *CyclicBarrier 迴圈屏障 *jdk:"一種同步幫助,允許一組執行緒等待所有執行緒,互相達到一個共同的障礙點",大白話講:滿足n個執行緒數量,才能訪問後續動作,不滿足就一直等待。 */ 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個迴圈障礙,5個執行緒執行完後,會解除阻塞,計數清零。然後迴圈重複此規則 CyclicBarrier cyclicBarrier = new CyclicBarrier(5); //定義一個快取執行緒池,如果有空閒的執行緒進行回收,否則建立新的執行緒 ExecutorService executors = Executors.newCachedThreadPool(); //這裡可以模擬不同的請求數來驗證,第一次可以迴圈5次,第二次迴圈6次,第三次迴圈10次,來觀察不同之處 //迴圈5次,剛好一組任務完成。 //迴圈6次,只能滿足第一組任務,第二組任務將一直等待,阻塞任務。 //迴圈十次,兩組任務都可以完成。 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區別:
阻塞區別:
CountDownLatch某一個或多個執行緒 ,等待其他執行緒執行完成之後,才能繼續執行。父執行緒等待子執行緒執行完成,才能繼續執行。
CyclicBarrier 一組執行緒互相等待,任何一個未執行完成,其他執行緒都需要等待。10個執行緒,全部完成,才能執行後續動作。
使用次數區別:
CountDownLatch倒計時門閂,每執行一次都是遞減1,await等於0時,結束阻塞,不可重複使用
CyclicBarrier迴圈屏障,每執行一次都是遞加1,barrier釋放完後,可繼續使用,重複迴圈使用。
鎖區別
CountDownLatch內部使用 Sync AQS 狀態來控制,volatile可見性控制執行緒間變數共享
CyclicBarrier內部使用ReentrantLock可重入鎖