好像倒計時計數器,調用CountDownLatch對象的countDown方法就將計數器減1,當到達0時,所有等待者就開始執行。
java.util.concurrent.CountDownLatch
一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數初始化CountDownLatch。由于調用了countDown()方法,所以在當前計數到達零之前,await方法會一直受阻塞。之后,會釋放所有等待的線程,await的所有后續調用都將立即返回。這種現象只出現一次——計數無法被重置。如果需要重置計數,請考慮使用CyclicBarrier。
CountDownLatch是一個通用同步工具,它有很多用途。將計數1初始化的CountDownLatch用作一個簡單的開/關鎖存器,或入口:在通過調用countDown()的線程打開入口前,所有調用await的線程都一直在入口處等待。用N初始化的 CountDownLatch可以使一個線程在N個線程完成某項操作之前一直等待,或者使其在某項操作完成N次之前一直等待。
CountDownLatch的一個有用特性是,它不要求調用countDown方法的線程等到計數到達零時才繼續,而在所有線程都能通過之前,它只是阻止任何線程繼續通過一個await。
舉例:多個運動員等待裁判命令:裁判等所有運動員到齊后發布結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package com.ljq.test.thread; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CountdownLatchTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); //裁判發布命令的計數器,計數器為0,運動員就跑 final CountDownLatch cdOrder = new CountDownLatch( 1 ); //運動員跑到終點的計數器,為0裁判宣布結果 final CountDownLatch cdAnswer = new CountDownLatch( 3 ); //產生3個運動員 for ( int i= 0 ;i< 3 ;i++){ Runnable runnable = new Runnable(){ public void run(){ try { System.out.println( "線程" + Thread.currentThread().getName() + "正準備接受命令" ); cdOrder.await(); System.out.println( "線程" + Thread.currentThread().getName() + "已接受命令" ); Thread.sleep(( long )(Math.random()* 10000 )); System.out.println( "線程" + Thread.currentThread().getName() + "回應命令處理結果" ); cdAnswer.countDown(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); //運動員開始任務 } try { //裁判休息一會 再發布命令 Thread.sleep(( long )(Math.random()* 10000 )); System.out.println( "線程" + Thread.currentThread().getName() + "即將發布命令" ); cdOrder.countDown(); //命令計數器置為0,發布命令 System.out.println( "線程" + Thread.currentThread().getName() + "已發送命令,正在等待結果" ); cdAnswer.await(); //等待所有運動員,計數器為0 所有運動員到位 System.out.println( "線程" + Thread.currentThread().getName() + "已收到所有響應結果" ); } catch (Exception e) { e.printStackTrace(); } service.shutdown(); } } |
返回結果:
1
2
3
4
5
6
7
8
9
10
11
12
|
線程pool- 1 -thread- 3 正準備接受命令 線程pool- 1 -thread- 1 正準備接受命令 線程pool- 1 -thread- 2 正準備接受命令 線程main即將發布命令 線程main已發送命令,正在等待結果 線程pool- 1 -thread- 2 已接受命令 線程pool- 1 -thread- 1 已接受命令 線程pool- 1 -thread- 3 已接受命令 線程pool- 1 -thread- 3 回應命令處理結果 線程pool- 1 -thread- 2 回應命令處理結果 線程pool- 1 -thread- 1 回應命令處理結果 線程main已收到所有響應結果 |