public class CountDownLatchTest01 {
public static void main(String[] args) throws InterruptedException {
//發令槍準備
CountDownLatch startSignal=new CountDownLatch(1);
//5個線程要一起到終點
CountDownLatch endSignal=new CountDownLatch(5);
for (int i = 0; i < 5; i++) {
new Thread(new WorkerTest(startSignal,endSignal),"我是:"+i).start();
}
TimeUnit.SECONDS.sleep(3);
startSignal.countDown();
System.out.println("裁判:所有線程準備完畢,預備,跑!");
endSignal.await();
System.out.println("裁判:友誼第一,比賽第二,大家都到終點了,一起坐車回家!");
}
}
class WorkerTest implements Runnable{
private CountDownLatch startSignal;
private CountDownLatch endSignal;
public WorkerTest(CountDownLatch startSignal, CountDownLatch endSignal) {
this.startSignal = startSignal;
this.endSignal = endSignal;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"線程,開始等待起跑口令。。。。");
startSignal.await();
System.out.println(Thread.currentThread().getName()+"線程,加速gogogo");
System.out.println(Thread.currentThread().getName()+"線程,到終點了,其他人呢");
endSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
CountDownLatch 被人稱作減法計數器,但是實際應用的時候,按照JDK文檔的解釋,可以有兩種場景適用。
第一個是作爲發令槍,場景是所有的線程在啓動的時候,調用CountDownLatch 的await方法進行阻塞,然後通過調用countDown()方法,讓阻塞的線程繼續執行,一般這樣我們可以new CountDownLatch(1)計數爲1
第二個是作爲一個上車關門條件,好比一輛巴士,要等所有乘客上車纔可以關門開車。主要判斷所有的線程執行完畢後,進行一些業務操作。此種場景下,一般是N個線程,則new CountDownLatch(N),然後在循環創建線程結束後,在主方法中調用await方法進行阻塞,最後在線程內部方法執行完畢後,進行countDown操作。這樣當所有線程執行完畢後,主線程纔會繼續執行。
上述代碼模擬5個線程進行跑步比賽,比賽完成後要一起坐車回家。運行結果如下:
我是:1線程,開始等待起跑口令。。。。
我是:4線程,開始等待起跑口令。。。。
我是:0線程,開始等待起跑口令。。。。
我是:3線程,開始等待起跑口令。。。。
我是:2線程,開始等待起跑口令。。。。
裁判:所有線程準備完畢,預備,跑!
我是:0線程,加速gogogo
我是:0線程,到終點了,其他人呢
我是:2線程,加速gogogo
我是:2線程,到終點了,其他人呢
我是:4線程,加速gogogo
我是:4線程,到終點了,其他人呢
我是:3線程,加速gogogo
我是:3線程,到終點了,其他人呢
我是:1線程,加速gogogo
我是:1線程,到終點了,其他人呢
裁判:友誼第一,比賽第二,大家都到終點了,一起坐車回家!
這其中要注意,第一次打印裁判所有線程準備完畢,預備,跑!如果沒有TimeUnit.SECONDS.sleep(3);打印出來的結果,會和線程的開始等待等,不會按照順序執行的。
爲了演示效果才添加了延遲,實際生產過程中,不能按照此方法來進行主線程與其他線程的同步。
思考:應用場景還有哪些?現在能想到一個,是可以作爲多線程併發的測試,比如循環創建1000個線程,最開始await,調用CountDown方法,來模擬線程併發的場景。
大家留言交流下,看看還有沒有其他適用場景?