【CountDownLatch、CyclicBarrier和Semaphore】
http://www.cnblogs.com/dolphin0520/p/3920397.html
http://www.cnblogs.com/dolphin0520/p/3920397.html
【CountDownLatch同步工具類】
CountDownLatch是什么
CountDownLatch是在java1.5被引入的,跟它一起被引入的並發工具類還有
CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它們都存在於java.util.concurrent包下。CountDownLatch這個類能夠使
一個線程等待其他線程完成各自的工作后再執行。例如,應用程序的主線程希望在負責啟動框架服務的線程已經啟動所有的框架服務之后再執行。
CountDownLatch是通過一個
計數器來實現的,計數器的初始值為線程的數量。每當一個線程完成了自己的任務后,計數器的值就會減1。當計數器值到達0時,它表示所有的線程已經完成了任務,然后在閉鎖上等待的線程就可以恢復執行任務。
CountDownLatch如何工作
CountDownLatch.java類中定義的構造函數:
//Constructs a CountDownLatch initialized with the given count.
public void CountDownLatch(int count) {...}
構造器中的計數值(count)實際上就是閉鎖需要等待的線程數量。這個值只能被設置一次,而且CountDownLatch沒有提供任何機制去重新設置這個計數值。
與CountDownLatch的第一次交互是主線程等待其他線程。主線程必須在啟動其他線程后立即調用
CountDownLatch.await()方法。這樣主線程的操作就會在這個方法上阻塞,直到其他線程完成各自的任務。
其他N 個線程必須引用閉鎖對象,因為他們需要通知CountDownLatch對象,他們已經完成了各自的任務。這種通知機制是通過
CountDownLatch.countDown()方法來完成的;每調用一次這個方法,在構造函數中初始化的count值就減1。所以當N個線程都調用了這個方法,count的值等於0,然后主線程就能通過await()方法,恢復執行自己的任務。
在實時系統中的使用場景
1.實現最大的並行性:有時我們想同時啟動多個線程,實現最大程度的並行性。例如,我們想測試一個單例類。如果我們創建一個初始計數為1的CountDownLatch,並讓所有線程都在這個鎖上等待,那么我們可以很輕松地完成測試。我們只需調用 一次countDown()方法就可以讓所有的等待線程同時恢復執行。
2.開始執行前等待n個線程完成各自任務:例如應用程序啟動類要確保在處理用戶請求前,所有N個外部系統已經啟動和運行了。
3.死鎖檢測:一個非常方便的使用場景是,你可以使用n個線程訪問共享資源,在每次測試階段的線程數目是不同的,並嘗試產生死鎖。
常見面試題
可以為你的下次面試准備以下一些CountDownLatch相關的問題:
解釋一下CountDownLatch概念?
CountDownLatch 和CyclicBarrier的不同之處?
給出一些CountDownLatch使用的例子?
CountDownLatch 類中主要的方法?
CountDownLatch(int)
await()
await(long,TimeUnit)
CountDown()
getCount()
toString
在網上看到很多人對於CountDownLatch和CyclicBarrier的區別簡單理解為
CountDownLatch是一次性的,而CyclicBarrier在調用reset之后還可以繼續使用。
那如果只是這么簡單的話,我覺得CyclicBarrier簡單命名為ResetableCountDownLatch好了,顯然不是的。
我的理解是,要從他們的設計目的去看這兩個類。javadoc里面的描述是這樣的。
CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CyclicBarrier : A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
CountDownLatch和CyclicBarrier本質是一樣的,都是在每個Thread 設置 CountDownLatch或CyclicBarrier 的屏障點point, 每個Thread 計入的Condition 中隊列, 執行到屏障點point時候,回調 CountDownLatch或CyclicBarrier 的await方法,在Condition 中隊列遍歷是否所有的Thread 都已經執行到屏障點point。但是並沒有釋放Thread ,Thread 一致是運行狀態(可以理解成時等待其他Thread全部完成屏障點point)。
區別是:
每個Thread 到達 CountDownLatch的屏障點point 可以調用 countDown()計數-1,到全部為計數0的時候,全部其他Thread通過,繼續執行或結束。
所有到達 CyclicBarrier 的屏障點point 時候,該屏障點point 結束,繼續執行。如果不能全部到達(中斷、失敗或者超時等原因),設置 BrokenBarrierException引起所有調用await方法的“Thread”全部報錯,全部要么全不 (all-or-none) 的破壞模式。
reset也是拋出BrokenBarrierException。
簡而言之,
CyclicBarrier 實現一致性,CountDownLatch簡單計數。