關於CyclicBarrier的執行順序
阿新 • • 發佈:2017-06-13
ren left p s 說明 star oop event @override open
- 認識CyclicBarrier, 先看兩個文檔介紹
CyclicBarrier(int parties, Runnable barrierAction)
int
await()
Waits until all parties have invoked await on this barrier.
- 舉例,示例代碼
1 public class Main { 2 3 private static CyclicBarrier barrier ; 4 5 public Main(){ 6 7 } 8 9 static class Worker implements Runnable{ 10 int id; 11 12 public示例代碼Worker(int i){ 13 id = i; 14 } 15 16 @Override 17 public void run() { 18 System.out.println("thread is working : "+id); 19 20 try { 21 barrier.await(); 22 } catch (InterruptedException e) { 23 e.printStackTrace();24 } catch (BrokenBarrierException e) { 25 e.printStackTrace(); 26 } 27 28 System.out.println("thread is ending : "+id); 29 } 30 } 31 32 public static void main(String[] args) { 33 34 barrier = new CyclicBarrier(2, new Runnable() { 35 @Override 36 public void run() { 37 try { 38 Thread.sleep(3000); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 System.out.println("Master is finished......."); 43 } 44 }); 45 46 for (int i=0;i<2;i++){ 47 Worker worker = new Worker(i); 48 new Thread(worker).start(); 49 } 50 51 } 52 }
- 問題:parties滿足全部進入await後,barrierAction與await的喚醒,誰先誰後?
- 實驗結果: 示例代碼執行結果
thread is working : 0
thread is working : 1
Master is finished.......
thread is ending : 1
thread is ending : 0
結果說明:CyclicBarrier中,當各參與方(parties)到達之後,構造函數中的barrier action會先執行,之後各線程的await才會再返回。
- JDK源代碼佐證:
1 private int dowait(boolean timed, long nanos) 2 throws InterruptedException, BrokenBarrierException, 3 TimeoutException { 4 final ReentrantLock lock = this.lock; 5 lock.lock(); 6 try { 7 final Generation g = generation; 8 9 if (g.broken) 10 throw new BrokenBarrierException(); 11 12 if (Thread.interrupted()) { 13 breakBarrier(); 14 throw new InterruptedException(); 15 } 16 17 int index = --count; 18 if (index == 0) { // tripped 19 boolean ranAction = false; 20 try { 21 final Runnable command = barrierCommand; 22 if (command != null) 23 command.run(); 24 ranAction = true; 25 nextGeneration(); 26 return 0; 27 } finally { 28 if (!ranAction) 29 breakBarrier(); 30 } 31 } 32 33 // loop until tripped, broken, interrupted, or timed out 34 for (;;) { 35 try { 36 if (!timed) 37 trip.await(); 38 else if (nanos > 0L) 39 nanos = trip.awaitNanos(nanos); 40 } catch (InterruptedException ie) { 41 if (g == generation && ! g.broken) { 42 breakBarrier(); 43 throw ie; 44 } else { 45 // We‘re about to finish waiting even if we had not 46 // been interrupted, so this interrupt is deemed to 47 // "belong" to subsequent execution. 48 Thread.currentThread().interrupt(); 49 } 50 } 51 52 if (g.broken) 53 throw new BrokenBarrierException(); 54 55 if (g != generation) 56 return index; 57 58 if (timed && nanos <= 0L) { 59 breakBarrier(); 60 throw new TimeoutException(); 61 } 62 } 63 } finally { 64 lock.unlock(); 65 } 66 }JDK CyclicBarrier源代碼
從代碼可以看出,barrierCommand執行(21行)之後,才在finally裏調用breakeBarrier(29行),從而喚醒其他線程。證明示例代碼的運行結論。
關於CyclicBarrier的執行順序