CyclicBarrier
一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因爲該 barrier 在釋放等待線程後可以重用,所以稱它爲循環 的 barrier。CyclicBarrier 支持一個可選的 Runnable 命令,在一組線程中的最後一個線程到達之後(但在釋放所有線程之前),該命令只在每個屏障點運行一次。若在繼續所有參與線程之前更新共享狀態,此屏障操作很有用。
可能這裏大家會比較疑惑CountDownLatch和CyclicBarrier究竟有什麼區別??
兩者主要用於多線程的併發執行。當一個線程需要等待另外一個或多個線程的執行時,就可以考慮用它倆。
共同點:
-
兩者的共同點是都具有await()方法,並且執行此方法會引起線程的阻塞,達到某種條件才能繼續執行(這種條件也是兩者的不同)。 -
還有一個共同點是其構造方法都接受一個int類型的參數,這個值作爲計數用,達到該次數即釋放等待的線程。
不同點:
-
CountDownLatch是減計數方式,計數==0時釋放所有等待的線程;CyclicBarrier是加計數方式,計數達到構造方法中參數指定的值時釋放所有等待的線程。 -
CountDownLatch當計數到0時,計數無法被重置;CyclicBarrier計數達到指定值時,計數置爲0重新開始。 -
CountDownLatch每次調用countDown()方法計數減一,調用await()方法只進行阻塞,對計數沒任何影響;CyclicBarrier只有一個await()方法,調用await()方法計數加1,若加1後的值不等於構造方法的值,則線程阻塞。
package com.uppower.thread;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(5, new TotalTask());
// 實際系統是查出所有省編碼code的列表,然後循環,每個code生成一個線程。
new BillTask(barrier, "北京").start();
new BillTask(barrier, "上海").start();
new BillTask(barrier, "廣西").start();
new BillTask(barrier, "四川").start();
new BillTask(barrier, "黑龍江").start();
}
static class TotalTask implements Runnable {
public void run() {
System.out.println("=======================================");
System.out.println("開始全國彙總");
try {
//doTotalBill() 讀取內存中各省的數據彙總,過程略。
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("全國彙總完畢");
System.out.println("=======================================");
}
}
/**
* 子任務:計費任務
*/
static class BillTask extends Thread {
private CyclicBarrier barrier;
// 代碼,按省代碼分類,各省數據庫獨立。
private String code;
BillTask(CyclicBarrier barrier, String code) {
this.barrier = barrier;
this.code = code;
}
public void run() {
System.out.println("開始計算--" + code + "省--數據!");
try {
//doBill()
Thread.sleep(5000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 把bill方法結果存入內存,如ConcurrentHashMap,vector等,代碼略
System.out.println(code + "省已經計算完成,並通知彙總Service!");
try {
// 通知barrier已經完成
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(" 全國彙總完畢了--" + code + "省又可以happy了!");
}
}
}
運行輸出結果:
開始計算--北京省--數據!
開始計算--廣西省--數據!
開始計算--四川省--數據!
開始計算--上海省--數據!
開始計算--黑龍江省--數據!
北京省已經計算完成,並通知彙總Service!
廣西省已經計算完成,並通知彙總Service!
黑龍江省已經計算完成,並通知彙總Service!
四川省已經計算完成,並通知彙總Service!
上海省已經計算完成,並通知彙總Service!
=======================================
開始全國彙總
全國彙總完畢
=======================================
全國彙總完畢了--北京省又可以happy了!
全國彙總完畢了--黑龍江省又可以happy了!
全國彙總完畢了--廣西省又可以happy了!
全國彙總完畢了--四川省又可以happy了!
全國彙總完畢了--上海省又可以happy了!