CountDownLatch和CycliBarrier介紹

1、CountDownLatch

  它被用來同步一個或多個任務,強制他們等待其餘任務完成,這就是閉鎖。app

public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

  類中只有一個構造函數,一個int類型的參數count,表明計數器。這個計數器的初始值是線程的數量,每當一個線程結束,count-1,當count==0 時,全部線程執行完畢,在閉鎖上等待的線程就能夠執行了。ide

類中還包含了三個公共方法:函數

public void await()
public boolean await(long timeout, TimeUnit unit)
public void countDown()

  當每一個任務完成時,都會調用countDown()方法。而等待問題被解決的任務在這個鎖存器上調用await()方法,這個任務就至關於被掛起了直到 timeout 或 計數器爲0this

public class CountDownLatchDemo {
    static final int SIZE = 5;

    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(5));
        CountDownLatch countDownLatch = new CountDownLatch(SIZE);
        pool.execute(new WaitTask(countDownLatch));
        for (int i = 0; i < SIZE; i++) {
            pool.execute(new TaskNow(countDownLatch));
        }
    }

}

class TaskNow implements Runnable {
    private final CountDownLatch countDownLatch;

    TaskNow(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        try {
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("我沒完事你別想跑");
        //調用countDown()的方法會減小count次數直到爲0,調用await的任務才能進行
        countDownLatch.countDown();
    }
}

class WaitTask implements Runnable {
    private final CountDownLatch countDownLatch;

    WaitTask(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        try {
            //調用await的任務會被掛起
            countDownLatch.await();
            System.out.println("終於輪到我了");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
結果:

  我沒完事你別想跑
  我沒完事你別想跑
  我沒完事你別想跑
  我沒完事你別想跑
  我沒完事你別想跑
  終於輪到我了spa

2、CylicBarrier

  柵欄相似於閉鎖,只是要等到全部線程都到達柵欄,才能進行接下來的動做,在沒到達柵欄以前先到的要等待。線程

構造方法

共有兩個構造方法:code

 

 

 

public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }
public CyclicBarrier(int parties) {
        this(parties, null);
    }

CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每一個線程使用await()方法告訴CyclicBarrier我已經到達了屏障,而後當前線程被阻塞。blog

CyclicBarrier的另外一個構造函數CyclicBarrier(int parties, Runnable barrierAction),用於線程到達屏障時,優先執行barrierAction,方便處理更復雜的業務場景。同步

await()方法

  線程調用await()方法表示已經到達同步點,而後當前線程被阻塞。直到parties個參與線程調用了await()方法,CyclicBarrier一樣提供帶超時時間的await和不帶超時時間的await方法:it

public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException{...}

 

  能夠看到await方法調用了dowait()方法,dowait()方法是核心方法其內容是:若是這個線程不是最後一個到達的線程那麼進行等待直到:

  • 最後一個線程到達,即index == 0
  • 某個參與線程等待超時
  • 某個參與線程被中斷
  • 調用了CyclicBarrier的reset()方法。該方法會將屏障重置爲初始狀態

案例

public class CycliBarrierDemo {


    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
        ThreadPoolExecutor pool = new ThreadPoolExecutor(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
        for (int i = 0; i < threadCount; i++) {
            pool.execute(new Horse(cyclicBarrier, i));
        }
    }
}

class Horse implements Runnable {
    private CyclicBarrier cyclicBarrier;
    private int num;

    public Horse(CyclicBarrier cyclicBarrier, int num) {
        this.cyclicBarrier = cyclicBarrier;
        this.num = num;
    }

    @Override
    public void run() {
        System.out.println("馬匹:" + num + "到了");
        try {
            cyclicBarrier.await();
            System.out.println("馬匹:" + num + "在等待");
            TimeUnit.MILLISECONDS.sleep(2000);
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("馬匹到齊");
    }
}


結果:

  馬匹:0到了  馬匹:2到了  馬匹:1到了  馬匹:1在等待  馬匹:0在等待  馬匹:2在等待  馬匹到齊  馬匹到齊  馬匹到齊

相關文章
相關標籤/搜索