1. 程式人生 > >Java併發程式設計--CountDownLatch配合執行緒池

Java併發程式設計--CountDownLatch配合執行緒池

Java併發程式設計–CountDownLatch配合執行緒池

在處理一些耗時操作的時候,我們習慣上會把它放在子執行緒裡面做,是的如果允許(我是指操作的內容),為了更快速地完成這堆操作,執行緒池是一個不錯的選擇。等等,好像有點不對,如果需要等待所有的執行緒在執行完後觸發一個操作,這個時候你就需要用到CountDownLatch。

其實這涉及到多執行緒非同步轉同步的問題,在java 1.5中,提供了一些非常有用的輔助類來幫助我們進行併發程式設計,比如CountDownLatch,CyclicBarrier和Semaphore,但是如果需要配合執行緒池使用,CountDownLatch是不錯的選擇(Semaphore還沒用過。。。所以沒選它)。

這裡先下個結論:

  1. CountDownLatch和CyclicBarrier都能夠實現執行緒之間的等待,只不過它們側重點不同;
  2. CountDownLatch一般用於某個執行緒A等待若干個其他執行緒執行完任務之後,它才執行;
  3. 而CyclicBarrier一般用於一組執行緒互相等待至某個狀態,然後這一組執行緒再同時執行;
  4. 另外,CountDownLatch是不能夠重用的,而CyclicBarrier是可以重用的。

先看看CountDownLatch提供的方法:
這裡寫圖片描述

CountDownLatch只有一個構造方法:

public CountDownLatch(int count) {  };  //引數count為計數值

然後下面這3個方法是CountDownLatch類中最重要的方法:

//呼叫await()方法的執行緒會被掛起,它會等待直到count值為0才繼續執行
public void await() throws InterruptedException { };   

//和await()類似,只不過等待一定的時間後count值還沒變為0的話就會繼續執行
public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  

//將count值減1
public void countDown() { };  

在看看CyclicBarrier的方法:

public CyclicBarrier(int parties, Runnable barrierAction) {
}

public CyclicBarrier(int parties) {
}

public int await() throws InterruptedException, BrokenBarrierException { };
public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { };

看完後你會發現CountDownLatch和CyclicBarrier兩者的await方法是會阻塞當前執行緒的,因此如果線上程池中使用CyclicBarrier,如果執行緒池的core大小小於parties,執行緒池中的執行緒遍一直處於阻塞狀態,相反CountDownLatch的countDown()在執行後,完美退出當前執行緒,但是在開啟呼叫CountDownLatch.await()的時候,需要在子執行緒中,否則就阻塞了當前執行緒。