CyclicBarrier循環屏障相關
阿新 • • 發佈:2018-05-13
lai sta 參考 value 兩個 runnable public .net 得到
簡介
CyclicBarrier 的字面意思是可循環使用(Cyclic)的屏障(Barrier)。它要做的事情是,讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續幹活。CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每個線程調用await方法告訴CyclicBarrier我已經到達了屏障,然後當前線程被阻塞。
實例代碼如下:
01 |
public class CyclicBarrierTest { |
02 |
03 |
static CyclicBarrier c = new CyclicBarrier( 2 ); |
04 |
05 |
public static void main(String[] args) { |
06 |
new Thread( new Runnable() { |
07 |
08 |
@Override |
09 |
public void run() { |
10 |
try { |
11 |
c.await(); |
12 |
} catch (Exception e) { |
13 |
14 |
} |
15 |
System.out.println( 1 ); |
16 |
} |
17 |
}).start(); |
18 |
19 |
try { |
20 |
c.await(); |
21 |
} catch (Exception e) { |
22 |
23 |
} |
24 |
System.out.println( 2 ); |
25 |
} |
26 |
} |
輸出
1 |
2 |
2 |
1 |
或者輸出
1 |
1 |
2 |
2 |
如果把new CyclicBarrier(2)修改成new CyclicBarrier(3)則主線程和子線程會永遠等待,因為沒有第三個線程執行await方法,即沒有第三個線程到達屏障,所以之前到達屏障的兩個線程都不會繼續執行。
CyclicBarrier還提供一個更高級的構造函數CyclicBarrier(int parties, Runnable barrierAction),用於在線程到達屏障時,優先執行barrierAction,方便處理更復雜的業務場景。代碼如下:
01 |
public class CyclicBarrierTest2 { |
02 |
03 |
static CyclicBarrier c = new CyclicBarrier( 2 , new A()); |
04 |
05 |
public static void main(String[] args) { |
06 |
new Thread( new Runnable() { |
07 |
08 |
@Override |
09 |
public void run() { |
10 |
try { |
11 |
c.await(); |
12 |
} catch (Exception e) { |
13 |
14 |
} |
15 |
System.out.println( 1 ); |
16 |
} |
17 |
}).start(); |
18 |
19 |
try { |
20 |
c.await(); |
21 |
} catch (Exception e) { |
22 |
23 |
} |
24 |
System.out.println( 2 ); |
25 |
} |
26 |
27 |
static class A implements Runnable { |
28 |
29 |
@Override |
30 |
public void run() { |
31 |
System.out.println( 3 ); |
32 |
} |
33 |
34 |
} |
35 |
36 |
} |
輸出
1 |
3 |
2 |
1 |
3 |
2 |
CyclicBarrier的應用場景
CyclicBarrier可以用於多線程計算數據,最後合並計算結果的應用場景。比如我們用一個Excel保存了用戶所有銀行流水,每個Sheet保存一個帳戶近一年的每筆銀行流水,現在需要統計用戶的日均銀行流水,先用多線程處理每個sheet裏的銀行流水,都執行完之後,得到每個sheet的日均銀行流水,最後,再用barrierAction用這些線程的計算結果,計算出整個Excel的日均銀行流水。
CyclicBarrier和CountDownLatch的區別
- CountDownLatch的計數器只能使用一次。而CyclicBarrier的計數器可以使用reset() 方法重置。所以CyclicBarrier能處理更為復雜的業務場景,比如如果計算發生錯誤,可以重置計數器,並讓線程們重新執行一次。
- CyclicBarrier還提供其他有用的方法,比如getNumberWaiting方法可以獲得CyclicBarrier阻塞的線程數量。isBroken方法用來知道阻塞的線程是否被中斷。比如以下代碼執行完之後會返回true。
isBroken的使用代碼如下:
01 |
import java.util.concurrent.BrokenBarrierException; |
02 |
import java.util.concurrent.CyclicBarrier; |
03 |
04 |
public class CyclicBarrierTest3 { |
05 |
06 |
static CyclicBarrier c = new CyclicBarrier( 2 ); |
07 |
08 |
public static void main(String[] args) throws InterruptedException, BrokenBarrierException { |
09 |
Thread thread = new Thread( new Runnable() { |
10 |
11 |
@Override |
12 |
public void run() { |
13 |
try { |
14 |
c.await(); |
15 |
} catch (Exception e) { |
16 |
} |
17 |
} |
18 |
}); |
19 |
thread.start(); |
20 |
thread.interrupt(); |
21 |
try { |
22 |
c.await(); |
23 |
} catch (Exception e) { |
24 |
System.out.println(c.isBroken()); |
25 |
} |
26 |
} |
27 |
} |
輸出
true
參考鏈接:http://ifeve.com/concurrency-cyclicbarrier/
參考鏈接:https://blog.csdn.net/zzg1229059735/article/details/61191679
CyclicBarrier循環屏障相關