介紹 一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程式中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程後可以重用,所以稱它為迴圈 的 barri
- 介紹
一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程式中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程後可以重用,所以稱它為迴圈 的 barrier。
CyclicBarrier 支持一個可選的 Runnable
命令,在一組線程中的最後一個線程到達之後(但在釋放所有線程之前),該命令只在每個屏障點運行一次。若在繼續所有參與線程之前更新共用狀態,此屏障操作 很有用。
- 主要方法
-
1 //設置parties、count及barrierCommand屬性。 2 CyclicBarrier(int): 3 //當await的數量到達了設定的數量後,首先執行該Runnable對象。 4 CyclicBarrier(int,Runnable): 5 //通知barrier已完成線程 6 await():
-
應用場景
1:CyclicBarrier 表示大家彼此等待,大家集合好後才開始出發,分散活動後又在i指定地點集合碰面,這就好比整個公司的人員利用周末時間集體郊游一樣,先各自從家出發到公司集合後,再同時出發到公園游玩,在指定地點集合後再同時開始就餐。
代碼:
1 public class CyclicBarrierTest { 2 public static void main(String[] args){ 3 ExecutorService pool = Executors.newCachedThreadPool(); 4 final CyclicBarrier cyclicBarrier = new CyclicBarrier(3); 5 6 for (int i = 0; i < 3; i++) { 7 Runnable runnable = new Runnable() { 8 @Override 9 public void run(){ 10 try { 11 Thread.sleep(new Random().nextInt(5000)); 12 } catch (InterruptedException e) { 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 } 16 System.out.println(Thread.currentThread().getName()+"到達地點一,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"繼續出發":"繼續等待")); 17 try { 18 cyclicBarrier.await();//障礙等待點 19 } catch (InterruptedException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } catch (BrokenBarrierException e) { 23 // TODO Auto-generated catch block 24 e.printStackTrace(); 25 } 26 try { 27 Thread.sleep(new Random().nextInt(5000)); 28 } catch (InterruptedException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 System.out.println(Thread.currentThread().getName()+"到達地點二,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"繼續出發":"繼續等待")); 33 try { 34 cyclicBarrier.await();//障礙等待點 35 } catch (InterruptedException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } catch (BrokenBarrierException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 try { 43 Thread.sleep(new Random().nextInt(5000)); 44 } catch (InterruptedException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 System.out.println(Thread.currentThread().getName()+"到達地點三,當前等待人數為"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"人齊了出發":"繼續等待")); 49 try { 50 cyclicBarrier.await();//障礙等待點 51 } catch (InterruptedException e) { 52 // TODO Auto-generated catch block 53 e.printStackTrace(); 54 } catch (BrokenBarrierException e) { 55 // TODO Auto-generated catch block 56 e.printStackTrace(); 57 } 58 } 59 }; 60 pool.execute(runnable); 61 } 62 pool.shutdown(); 63 } 64 }
執行結果:
1 pool-1-thread-3到達地點一,當前等待人數為1繼續等待 2 pool-1-thread-1到達地點一,當前等待人數為2繼續等待 3 pool-1-thread-2到達地點一,當前等待人數為3繼續出發 4 pool-1-thread-1到達地點二,當前等待人數為1繼續等待 5 pool-1-thread-3到達地點二,當前等待人數為2繼續等待 6 pool-1-thread-2到達地點二,當前等待人數為3繼續出發 7 pool-1-thread-3到達地點三,當前等待人數為1繼續等待 8 pool-1-thread-2到達地點三,當前等待人數為2繼續等待 9 pool-1-thread-1到達地點三,當前等待人數為3人齊了出發View Code
2:在某種需求中,比如一個大型的任務,常常需要分配好多子任務去執行,只有當所有子任務都執行完成時候,才能執行主任務,這時候,就可以選擇CyclicBarrier了。
代碼:
1 public class CyclicBarrierTest1 { 2 public static void main(String[] args) { 3 ExecutorService threadPool = Executors.newCachedThreadPool(); 4 CyclicBarrier barrier = new CyclicBarrier(5, new mainTask()); 5 for (int i = 0; i < 5; i++) { 6 subTask subTask = new subTask(barrier); 7 threadPool.execute(subTask); 8 } 9 threadPool.shutdown(); 10 } 11 } 12 13 class subTask implements Runnable{ 14 private CyclicBarrier barrier; 15 16 public subTask(CyclicBarrier barrier) { 17 super(); 18 this.barrier = barrier; 19 } 20 @Override 21 public void run() { 22 System.out.println(Thread.currentThread().getName()+"正在執行"); 23 try { 24 Thread.sleep(5000); 25 } catch (InterruptedException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } 29 System.out.println(Thread.currentThread().getName()+"執行完畢,等待其他結果"); 30 try { 31 barrier.await(); 32 } catch (InterruptedException e) { 33 // TODO Auto-generated catch block 34 e.printStackTrace(); 35 } catch (BrokenBarrierException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } 39 40 } 41 } 42 class mainTask implements Runnable{ 43 44 @Override 45 public void run() { 46 System.out.println("總任務執行完畢"); 47 } 48 49 }
執行結果:
1 pool-1-thread-2正在執行 2 pool-1-thread-3正在執行 3 pool-1-thread-1正在執行 4 pool-1-thread-4正在執行 5 pool-1-thread-5正在執行 6 pool-1-thread-2執行完畢,等待其他結果 7 pool-1-thread-5執行完畢,等待其他結果 8 pool-1-thread-1執行完畢,等待其他結果 9 pool-1-thread-4執行完畢,等待其他結果 10 pool-1-thread-3執行完畢,等待其他結果 11 總任務執行完畢View Code
另外,CyclicBarrier是可以重用的,它可以在使用完後繼續使用,這就是Cyclic(迴圈)的意思。