Java併發工具類CountDownLatch和CyclicBarrier

Java併發工具類CountDownLatch和CyclicBarrier


1.CountDownLatch
CountDownLatch允許一個或多個線程等待其他線程完成操作,其構造函數接收一個int型的參數作爲計數器,若想等待N個點完成,就傳人N。此處的N個點,可指N個線程,也可以是1個線程中的N個步驟。
主要的方法爲CountDown()和await()。當調用CountDown()時,N會減1,await()方法會阻塞當前線程,直到N變爲零。
計數器必須大於等於0,只要等到0時候,調用await方法不會阻塞當前線程。CountDownLatch不可能重新初始化或者修改CountDownLatch對象內部的計數器值。一個線程調用countDown方法happen-before,另外一個線程調用await方法。
2.CyclicBarrier
CyclicBarrier讓一組線程到達一個屏障(或同步點)時被阻塞,直到最後一個線程到達屏障,屏障纔會被打開,所有被阻塞的線程纔會繼續執行。
CyclicBarrier默認的構造方法爲CyclicBarrier(int parties),其參數代表屏障被攔截的線程數,每個線程要調用CyclicBarrier對象的await方法,通知屏障線程已經到達同步點,然後該線程被阻塞。
CyclicBarrier的高級構造方法爲CyclicBarrier(intparties,Runnable barrierAction),用於在所有的線程都到達屏障時,優先執行barrierAction,然後執行被阻塞的線程。
CyclicBarrier可以應用於多線程計算數據,然後合併計算結果的場景。例如,用一個Excel保存了用戶所有的銀行流水,每個sheet保存一個賬戶近一年的每筆流水,現在需要統計用戶的日均流水,先用多線程處理每個sheet裏的銀行流水,都執行完之後,得到每個sheet的日均流水,最後,再用barrierAction用這些線程的計算結果,計算出整個Excel的日均銀行流水。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.Map.Entry;


public class BankWorkerService implements Runnable{


    private CyclicBarrier c = new CyclicBarrier(4, this);


    private Executor exe = Executors.newFixedThreadPool(4);


    private ConcurrentHashMap<String,sheetBankWaterCount =  
    new ConcurrentHashMap<String, Integer>();


    private void count() {
        for (int i = 0; i < 4; i++) {
            exe.execute(new Runnable() {


                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    sheetBankWaterCount.put
                    (Thread.currentThread().getName(), 1);
                    try {
                        try {
                            c.await();
                            (Thread.currentThread().
                              getName());
                            } catch (BrokenBarrierException 
                            e) {


                            e.printStackTrace();
                        }
                    }catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            });
        }
    }


    @Override
    public void run() {


        int result = 0;
        for (Entry<String, Integer> sheet : 
        sheetBankWaterCount.entrySet()) {
            result += sheet.getValue();
        }


        sheetBankWaterCount.put("result", result);
        System.out.println(Thread.currentThread().
        getName());
    }


    public static void main(String[] args) {
        BankWorkerService bankWaterCount = new    
        BankWorkerService();
        bankWaterCount.count();
    }


}
  ● 1
  ● 
輸出
4
pool-1-thread-4
pool-1-thread-4
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
  ● 
3.CyclicBarrier和CountDownLatch的區別
CountDownLacth的計數器只能使用一次,
而CyclicBarrier的計數器可以使用reset方法重置。
所以CyclicBarrier能處理更爲複雜的業務場景。例如,
若計算髮生錯誤,可以重置計數器,並讓線程重新執行一次。
CyclicBarrier還提供其他有用的方法,比如getNumberWaiting方法可以獲得CyclicBarrier阻塞的線程數量。
isBroken()方法用來了解阻塞的線程是否被中斷。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章