- 阻塞隊列
- 閉鎖
- 柵欄
- FutuerTask
- 信號量
同步工具類可以根據自身的狀態來協調線程的控制流。
同步工具類都包含特定的結構化屬性,封裝了一些狀態,這些狀態覺得指定同步工具類的線程是繼續執行還是等待。同時,提供了操作狀態的方法。
阻塞隊列
阻塞隊列不僅能作爲保存對象的容器,還能協調生產者和消費者等線程之間的控制流。take和put等方法將阻塞,直到隊列達到期望的狀態。
閉鎖
閉鎖是一種同步工具類,可以延遲線程進度直到其到達終止狀態。閉鎖的作用相當於一扇門,閉鎖到達結束狀態之前,這扇門一直是關閉的,並且沒有任何線程能通過,當結束時,這扇門會打開,並且允許所有線程通過。閉鎖可以用來確保某些活動直到其他活動都完成後才繼續執行。
比如:確保某個計算在所有依賴的資源都被初始化之後才繼續執行,等到直到某個操作的所有參與者都準備就緒再繼續執行。
閉鎖狀態包括計數器,被初始化爲一個整數,等待的每個任務完成之後-1,當計數器變成0之後表示等待的所有事件都已經完成了,可以進行後續的計算了。
CountDownLatch是一種實現。
FutureTask
FutureTask通過Callable來實現的,有三種狀態,等待運行、正在運行和運行完成。完成包括正常結束、取消導致結束和異常導致結束。
當程序中有耗時的操作,並且可以分爲多個可以並行執行的流程,然後最後聚合結果的時候,可以考慮使用FutureTask來加速執行
public T someMethod(){
FutureTask<T> task1= new FutureTask(....);
FutureTask<T> task2= new FutureTask(....);
FutureTask<T> task3= new FutureTask(....);
executor.submit(task1);
executor.submit(task2);
executor.submit(task3);
try{
task1.get();
task2.get();
task3.get();
// 聚合操作
}catch(Exception e){
// 異常處理
}
// ...
}
信號量
計數信號量可以控制同時訪問某個特定資源的操作數量。
Semaphore中管理者一組虛擬的permit,在初始化時指定數量,執行之前先獲取許可,使用之後釋放。
柵欄
柵欄類似於閉鎖,能阻塞一組線程知道某個事件發生。
區別:柵欄與閉鎖關鍵區別在於所有線程必須同時到達柵欄位置,才能繼續執行。閉鎖用於等待事件,柵欄用於等待其他線程(參考:https://www.cnblogs.com/steffen/p/11244715.html)。CyclicBarrier是一種實現,可以使一定數量的參與方反覆在柵欄位置執行。
Exchanger也是另一種柵欄,可以用於兩個線程之間交換數據,可以參考(https://www.jianshu.com/p/990ae2ab1ae0,https://blog.csdn.net/octopusflying/article/details/80634864)