CyclicBarrier是一個同步輔助類,它容許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待,此時 CyclicBarrier 頗有用。由於該 barrier 在釋放等待線程後能夠重用,因此稱它爲循環 的 barrier。html
CyclicBarrier相似於CountDownLatch也是個計數器, 不一樣的是CyclicBarrier數的是調用了CyclicBarrier.await()進入等待的線程數, 當線程數達到了CyclicBarrier初始時規定的數目時,全部進入等待狀態的線程被喚醒並繼續。 CyclicBarrier就象它名字的意思同樣,可當作是個障礙, 全部的線程必須到齊後才能一塊兒經過這個障礙。 CyclicBarrier初始時還可帶一個Runnable的參數,此Runnable任務在CyclicBarrier的數目達到後,全部其它線程被喚醒前被執行。java
構造方法摘要 |
---|
CyclicBarrier(int parties) 建立一個新的 CyclicBarrier,它將在給定數量的參與者(線程)處於等待狀態時啓動,但它不會在每一個 barrier 上執行預約義的操做。 |
CyclicBarrier(int parties, Runnable barrierAction) 建立一個新的 CyclicBarrier,它將在給定數量的參與者(線程)處於等待狀態時啓動,並在啓動 barrier 時執行給定的屏障操做,該操做由最後一個進入 barrier 的線程執行 |
方法摘要 | |
---|---|
int |
await() 在全部 參與者 都已經在此 barrier 上調用 await 方法以前,將一直等待。 |
int |
await(long timeout, TimeUnit unit) 在全部 參與者 都已經在此屏障上調用 await 方法以前,將一直等待。 |
int |
getNumberWaiting() 返回當前在屏障處等待的參與者數目。 |
int |
getParties() 返回要求啓動此 barrier 的參與者數目。 |
boolean |
isBroken() 查詢此屏障是否處於損壞狀態。 |
void |
reset() 將屏障重置爲其初始狀態。 |
1 package com.thread; 2 import java.util.concurrent.CyclicBarrier; 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.Semaphore; 6 7 public class CyclicBarrierTest { 8 9 public static void main(String[] args) { 10 ExecutorService service = Executors.newCachedThreadPool(); 11 final CyclicBarrier cb = new CyclicBarrier(3);//建立CyclicBarrier對象並設置3個公共屏障點 12 for(int i=0;i<3;i++){ 13 Runnable runnable = new Runnable(){ 14 public void run(){ 15 try { 16 Thread.sleep((long)(Math.random()*10000)); 17 System.out.println("線程" + Thread.currentThread().getName() + 18 "即將到達集合地點1,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 19 cb.await();//到此若是沒有達到公共屏障點,則該線程處於等待狀態,若是達到公共屏障點則全部處於等待的線程都繼續往下運行 20 21 Thread.sleep((long)(Math.random()*10000)); 22 System.out.println("線程" + Thread.currentThread().getName() + 23 "即將到達集合地點2,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 24 cb.await(); 25 Thread.sleep((long)(Math.random()*10000)); 26 System.out.println("線程" + Thread.currentThread().getName() + 27 "即將到達集合地點3,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 28 cb.await(); 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 }; 34 service.execute(runnable); 35 } 36 service.shutdown(); 37 } 38 }
線程pool-1-thread-1即將到達集合地點1,當前已有0個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點1,當前已有1個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點1,當前已有2個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點2,當前已有0個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點2,當前已有1個已經到達,正在等候 線程pool-1-thread-1即將到達集合地點2,當前已有2個已經到達,正在等候 線程pool-1-thread-1即將到達集合地點3,當前已有0個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點3,當前已有1個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點3,當前已有2個已經到達,正在等候
若是在構造CyclicBarrier對象的時候傳了一個Runnable對象進去,則每次到達公共屏障點的時候都最早執行這個傳進去的Runnable,而後再執行處於等待的Runnable。若是把上面的例子改爲下面這樣:dom
1 package com.thread; 2 import java.util.concurrent.CyclicBarrier; 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.Semaphore; 6 7 public class CyclicBarrierTest { 8 9 public static void main(String[] args) { 10 ExecutorService service = Executors.newCachedThreadPool(); 11 //final CyclicBarrier cb = new CyclicBarrier(3);//建立CyclicBarrier對象並設置3個公共屏障點 12 final CyclicBarrier cb = new CyclicBarrier(3,new Runnable(){ 13 @Override 14 public void run() { 15 System.out.println("********我最早執行***********"); 16 } 17 }); 18 for(int i=0;i<3;i++){ 19 Runnable runnable = new Runnable(){ 20 public void run(){ 21 try { 22 Thread.sleep((long)(Math.random()*10000)); 23 System.out.println("線程" + Thread.currentThread().getName() + 24 "即將到達集合地點1,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 25 cb.await();//到此若是沒有達到公共屏障點,則該線程處於等待狀態,若是達到公共屏障點則全部處於等待的線程都繼續往下運行 26 27 Thread.sleep((long)(Math.random()*10000)); 28 System.out.println("線程" + Thread.currentThread().getName() + 29 "即將到達集合地點2,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 30 cb.await(); //這裏CyclicBarrier對象又能夠重用 31 Thread.sleep((long)(Math.random()*10000)); 32 System.out.println("線程" + Thread.currentThread().getName() + 33 "即將到達集合地點3,當前已有" + cb.getNumberWaiting() + "個已經到達,正在等候"); 34 cb.await(); 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 } 39 }; 40 service.execute(runnable); 41 } 42 service.shutdown(); 43 } 44 }
則結果以下:ide
線程pool-1-thread-1即將到達集合地點1,當前已有0個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點1,當前已有1個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點1,當前已有2個已經到達,正在等候 ********我最早執行*********** 線程pool-1-thread-1即將到達集合地點2,當前已有0個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點2,當前已有1個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點2,當前已有2個已經到達,正在等候 ********我最早執行*********** 線程pool-1-thread-1即將到達集合地點3,當前已有0個已經到達,正在等候 線程pool-1-thread-3即將到達集合地點3,當前已有1個已經到達,正在等候 線程pool-1-thread-2即將到達集合地點3,當前已有2個已經到達,正在等候 ********我最早執行***********