執行緒同步工具CyclicBarrier的使用
上一節中總結了Semaphore同步工具的使用,Semaphore主要提供了一個記數訊號量,允許最大執行緒數執行。CyclicBarrier是另一個同步工具,這一節主要來總結一下CyclicBarrier的使用。先看一下官方的對CyclicBarrier的介紹:
一個同步輔助類,它允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的執行緒的程式中,這些執行緒必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待執行緒後可以重用,所以稱它為迴圈 的 barrier。
我的解釋是這樣的:
CyclicBarrier 可以使不同的執行緒彼此等待,在不同的執行緒都執行完了後,再執行下面的程式。比如A、B、C三個同學要去玩,大巴在校門口,A、B、C分別從各自的寢室出來,先後到達大巴處,先來的必須等待,直到三個同學都來了,大巴才能走。他們要玩兩個地方M和N,到了M處,三個同學又各自去玩了,玩完後各自回到大巴上,先回來的必須等待,直到三個同學都到了,大巴才能到N處,這個大巴可以迴圈利用。這個大巴就是CyclicBarrier。
CyclicBarrier 同步工具相對來說比較簡單,因為功能很明確,下面寫一個CyclicBarrier 的示例程式碼:
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3); //設定要三個執行緒等待,都執行完了再往下執行
System.out.println("初始化:當前有" + (cb.getNumberWaiting() + "個執行緒在等待"));
//3個任務
for (int i = 0; i < 3; i++) {
Runnable run = new Runnable() {
public void run() {
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println(Thread.currentThread().getName()
+ "即將到達集合點1,當前已有" + (cb.getNumberWaiting()+1) + "個執行緒到達,"
+ (cb.getNumberWaiting()==2?"都到齊了,去集合點2!":"正在等候……"));
// 訪問完後,釋放 ,如果遮蔽下面的語句,則在控制檯只能列印3條記錄,之後執行緒一直阻塞
cb.await(); //等待
Thread.sleep((long)(Math.random()*10000));
System.out.println(Thread.currentThread().getName()
+ "即將到達集合點2,當前已有" + (cb.getNumberWaiting()+1) + "個執行緒到達,"
+ (cb.getNumberWaiting()==2?"都到齊了,去集合點3!":"正在等候……"));
cb.await();
Thread.sleep((long)(Math.random()*10000));
System.out.println(Thread.currentThread().getName()
+ "即將到達集合點3,當前已有" + (cb.getNumberWaiting()+1) + "個執行緒到達,"
+ (cb.getNumberWaiting()==2?"都到齊了,執行完畢!":"正在等候……"));
cb.await();
} catch (Exception e) {
}
}
};
service.execute(run); //執行任務
}
service.shutdown(); //關閉執行緒
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
從程式碼中可以看出,CyclicBarrier 的使用主要有兩點,一是初始化,二是呼叫await()方法。這個await()方法也就是官方解釋中的“公共屏障點”,到了這個點,所有執行緒都得等待,直到規定數量的執行緒全部到達才能往下執行。看一下執行效果:
初始化:當前有0個執行緒在等待 pool-1-thread-3即將到達集合點1,當前已有1個執行緒到達,正在等候…… pool-1-thread-2即將到達集合點1,當前已有2個執行緒到達,正在等候…… pool-1-thread-1即將到達集合點1,當前已有3個執行緒到達,都到齊了,去集合點2! pool-1-thread-2即將到達集合點2,當前已有1個執行緒到達,正在等候…… pool-1-thread-3即將到達集合點2,當前已有2個執行緒到達,正在等候…… pool-1-thread-1即將到達集合點2,當前已有3個執行緒到達,都到齊了,去集合點3! pool-1-thread-3即將到達集合點3,當前已有1個執行緒到達,正在等候…… pool-1-thread-1即將到達集合點3,當前已有2個執行緒到達,正在等候…… pool-1-thread-2即將到達集合點3,當前已有3個執行緒到達,都到齊了,執行完畢!
CyclicBarrier 的應用場合也很明顯:在某種需求中,比如一個大型的任務,常常需要分配好多子任務去執行,只有當所有子任務都執行完成時候,才能執行主任務,這時候,就可以選擇CyclicBarrier了。 可以再確切一點:假如我們需要統計全國的業務資料,其中各省的資料庫是獨立的,也就是說按省分庫。並且統計的資料量很大,統計過程也比較慢。為了提高效能,快速計算。我們採取併發的方式,多個執行緒同時計算各省資料,最後再彙總統計,在這裡CyclicBarrier就非常有用。 關於CyclicBarrier 同步工具就總結這麼多吧!