因為在調用端的異步中,需要調用其他多個服務獲取數據再匯總結果返回,所以用到了CountDownLatch
CountDownLatch的概念
CountDownLatch是一個同步工具類,用來協調多個線程之間的同步,或者說起到線程之間的通信(而不是用作互斥的作用)。
CountDownLatch能夠使一個線程在等待另外一些線程完成各自工作之后,再繼續執行。使用一個計數器進行實現。計數器初始值為線程的數量。當每一個線程完成自己任務后,計數器的值就會減一。當計數器的值為0時,表示所有的線程都已經完成了任務,然后在CountDownLatch上等待的線程就可以恢復執行任務。
CountDownLatch的用法
CountDownLatch典型用法1:某一線程在開始運行前等待n個線程執行完畢。將CountDownLatch的計數器初始化為n new CountDownLatch(n)
,每當一個任務線程執行完畢,就將計數器減1 countdownlatch.countDown()
,當計數器的值變為0時,在CountDownLatch上 await()
的線程就會被喚醒。一個典型應用場景就是啟動一個服務時,主線程需要等待多個組件加載完畢,之后再繼續執行。
CountDownLatch典型用法2:實現多個線程開始執行任務的最大并行性。注意是并行性,不是并發,強調的是多個線程在某一時刻同時開始執行。類似于賽跑,將多個線程放到起點,等待發令槍響,然后同時開跑。做法是初始化一個共享的CountDownLatch(1),將其計數器初始化為1,多個線程在開始執行任務前首先 coundownlatch.await()
,當主線程調用 countDown()
時,計數器變為0,多個線程同時被喚醒。
CountDownLatch的不足
CountDownLatch是一次性的,計數器的值只能在構造方法中初始化一次,之后沒有任何機制再次對其設置值,當CountDownLatch使用完畢后,它不能再次被使用。
?
CountDownLatch使用案例
需求:解析一個文件下多個txt文件數據,可以考慮使用多線程并行解析以提高解析效率。每一個線程解析一個文件里的數據,等到所有數據解析完畢之后再進行其他操作。
設計分析:在這個需求中,需要實現主線程等待所有線程完成文件解析操作,CountDownLatch正好可以做到。

CountDownLatch源碼分析
CountDownLatch是自定義AQS同步組件,是AQS的一個非常簡單的實現,接下來就以自定義同步器Sync、countDown方法和await方法為切入點,分析CountDownLatch的具體實現。
-
自定義同步器Sync實現[s??k]
自定義同步器實現同步器Sync實現了共享式獲取同步狀態的acquire和release,前文中已經詳細介紹過AQS相關內容,在這里我就不再做詳細介紹分析了。
-
構造方法
構造方法從構造方法的具體實現可以看出,通過構造方法傳入的int型參數count其實就是同步器的狀態State。
-
countDown實現
countDown實現整個countDown只做了一件事情,釋放同步狀態,同步狀態在這里的實際意義也就是需要等待的完成的點的數量,只要每完成一個點,就調用countDown方法釋放同步狀態。
-
await實現
CountDownLatch提供帶超時時間的await和不帶超時時間的await:await實現await的實質是在獲取同步狀態,同步狀態state == 0成立,當前等待完成的點均已完成,主線程繼續往下執行,否則,主線程進入等待隊列自旋等待直到同步狀態釋放后state == 0。有些時候主線程是不能一直自旋等待,這個時候帶超時時間的await就派上用場了,設置超時時間,如果在指定時間內N個點都未完成,返回false,主線程不再等待,繼續往下執行。
參考AQS結構圖方便理解:
?
總結:CountDownLatch實質上就是一個AQS計數器,通過AQS來實現線程的等待與喚醒。
鏈接:https://www.jianshu.com/p/bce9f156080f
https://blog.csdn.net/joenqc/article/details/76794356