25.大白話說java並發工具類-CountDownLatch,CyclicBarrier,Semaphore,Exchanger
在多線程協作完成業務功能時,有時候需要等待其他多個線程完成任務之後,主線程才能繼續往下執行業務功能,在這種的業務場景下,通常可以使用Thread類的join方法,讓主線程等待被join的線程執行完之後,主線程才能繼續往下執行。當然,使用線程間消息通信機制也可以完成。其實,java並發工具類中為我們提供了類似“倒計時”這樣的工具類,可以十分方便的完成所說的這種業務場景。
為了能夠理解CountDownLatch,舉一個很通俗的例子,運動員進行跑步比賽時,假設有6個運動員參與比賽,裁判員在終點會為這6個運動員分別計時,可以想象每當一個運動員到達終點的時候,對於裁判員來說就少了一個計時任務。直到所有運動員都到達終點了,裁判員的任務也才完成。這6個運動員可以類比成6個線程,當線程調用CountDownLatch.countDown方法時就會對計數器的值減一,直到計數器的值為0的時候,裁判員(調用await方法的線程)才能繼續往下執行。
下面來看些CountDownLatch的一些重要方法。
先從CountDownLatch的構造方法看起:
public CountDownLatch(int count)
構造方法會傳入一個整型數N,之後調用CountDownLatch的countDown
方法會對N減一,直到N減到0的時候,當前調用await
方法的線程繼續執行。
CountDownLatch的方法不是很多,將它們一個個列舉出來:
-
await() throws InterruptedException:調用該方法的線程等到構造方法傳入的N減到0的時候,才能繼續往下執行;
-
await(long timeout, TimeUnit unit):與上面的await方法功能一致,只不過這裏有了時間限制,調用該方法的線程等到指定的timeout時間後,不管N是否減至為0,都會繼續往下執行;
-
countDown():使CountDownLatch初始值N減1;
-
long getCount():獲取當前CountDownLatch維護的值;
下面用一個具體的例子來說明CountDownLatch的具體用法:
public class CountDownLatchDemo {
private static CountDownLatch startSignal = new CountDownLatch(1);
//用來表示裁判員需要維護的是6個運動員
private static CountDownLatch endSignal = new CountDownLatch(6);
?
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(6);
for (int i = 0; i < 6; i++) {
executorService.execute(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 運動員等待裁判員響哨!!!");
startSignal.await();
System.out.println(Thread.currentThread().getName() + "正在全力沖刺");
endSignal.countDown();
System.out.println(Thread.currentThread().getName() + " 到達終點");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
Thread.sleep(10);
System.out.println("裁判員發號施令啦!!!");
startSignal.countDown();
endSignal.await();
System.out.println("所有運動員到達終點,比賽結束!");
executorService.shutdown();
}
}
輸出結果:
?
pool-1-thread-2 運動員等待裁判員響哨!!!
pool-1-thread-3 運動員等待裁判員響哨!!!
pool-1-thread-1 運動員等待裁判員響哨!!!
pool-1-thread-4 運動員等待裁判員響哨!!!
pool-1-thread-5 運動員等待裁判員響哨!!!
pool-1-thread-6 運動員等待裁判員響哨!!!
裁判員發號施令啦!!!
pool-1-thread-2正在全力沖刺
pool-1-thread-2 到達終點
pool-1-thread-3正在全力沖刺
pool-1-thread-3 到達終點
pool-1-thread-1正在全力沖刺
pool-1-thread-1 到達終點
pool-1-