定義
CyclicBarrier:Cyclic(循環),Barrier(屏障)。循環屏障或者循環柵欄,它的功能就是,讓一組線程到達一個屏障時被阻塞,直到最後一個線程到達屏障時,屏障纔會打開,此時被阻塞的線程就會繼續執行。當線程調用CyclicBarrier的await()方法後,相當於告訴CyclicBarrier我到達了屏障,然後當前線程就會被阻塞。
應用場景
CyclicBarrier可以用於多個線程計算結果,最後合併計算結果的場景。
代碼清單
CyclicBarrier的定義爲3,即當有3個線程到達屏障時,就會打開屏障,讓這三個線程繼續往下執行。
package com.mark.learning.concurrent2.flowcontrol.cyclicbarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicBarrierDemo1 {
/** 定義CyclicBarrier,屏障大小爲3 **/
private static final CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("所有線程都到齊了,統一出發");
}
});
public static void main(String[] args) {
//聲明一個固定大小的線程池,線程容量爲5
ExecutorService executorService = Executors.newFixedThreadPool(5);
//執行10個子任務
for (int i = 0; i < 10; i++) {
executorService.execute(new Task(cyclicBarrier));
}
executorService.shutdown();
}
private static class Task implements Runnable {
private CyclicBarrier cyclicBarrier;
private Task(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "到達了集合地點,正在等待其他線程");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + "出發!");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
運行結果
實例中屏障的大小爲3,任務數量爲10。3個任務爲一組依次通過屏障,那麼最後有一個任務被阻塞住,因爲沒有多餘的兩個線程到達屏障了。
CyclicBarrier和CountDownLath的區別
- 作用不用:CyclicBarrier需要等待一定數量的線程到達屏障後,這些線程才能繼續執行,顯而易見CyclicBarrier面向的是線程。CountDownLath是等待計數爲0時,而計數減一這個操作不定義是有由一個線程執行了,可以在一個線程中進行多次減一,CountDownLath面向的事件。
- 可重用性不同:CountDownLath在倒數到0時,門閂打開後就不能再次使用了。而CyclicBarrier可以複用。