CountDownLatch是一個非常實用的多線程控制工具類。常用的就下面幾個方法:
CountDownLatch(int count) //實例化一個倒計數器,count指定計數個數
countDown() // 計數減一
await() //等待,當計數減到0時,所有線程並行執行
CountDownLatch在我工作的多個場景被使用,算是用的很頻繁的了,比如我們的API接口響應時間被要求在200ms以內,但是如果一個接口內部依賴多個三方/外部服務,那串行調用接口的RT必然很久,所以個人用的最多的是接口RT優化場景,內部服務並行調用。
對於倒計數器,一種典型的場景就是火箭發射。在火箭發射前,爲了保證萬無一失,往往還要進行各項設備、儀器的檢測。只有等到所有的檢查完畢後,引擎才能點火。那麼在檢測環節當然是多個檢測項可以同時進行的。代碼實現:
/**
* @Author: 王琦 <QQ.Eamil>[email protected]</QQ.Eamil>
* @Date: 2019-5-4 0004 9:43
* @Description: 倒計時器示例:火箭發射
*/
public class CountDownLatchDemo implements Runnable{
static final CountDownLatch latch = new CountDownLatch(10);
static final CountDownLatchDemo demo = new CountDownLatchDemo();
@Override
public void run() {
// 模擬檢查任務
try {
Thread.sleep(new Random().nextInt(10) * 1000);
System.out.println("check complete");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//計數減一
//放在finally避免任務執行過程出現異常,導致countDown()不能被執行
latch.countDown();
}
}
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newFixedThreadPool(10);
for (int i=0; i<10; i++){
exec.submit(demo);
}
// 等待檢查
latch.await();
// 發射火箭
System.out.println("Fire!");
// 關閉線程池
exec.shutdown();
}
}
上述代碼中我們先生成了一個CountDownLatch實例。計數數量爲10,這表示需要有10個線程來完成任務,等待在CountDownLatch上的線程才能繼續執行。latch.countDown();方法作用是通知CountDownLatch有一個線程已經準備完畢,倒計數器可以減一了。latch.await()方法要求主線程等待所有10個檢查任務全部準備好才一起並行執行。