CountDownLatch
是一個多執行緒同步工具類,在多執行緒環境中它允許多個執行緒處於等待狀態,直到前面的執行緒執行結束。從類別名稱上看CountDown
既是數量遞減的意思,我們可以把它理解為計數器。
countDown()
:計數器遞減方法。
await()
:讓呼叫此方法的執行緒進入等待狀態,直到計數器計數為0時主執行緒才會被喚醒。
await(long, TimeUnit)
:在await()
方法的基礎上增加了超時策略,若等待逾時仍未有結果則會直接喚醒主執行緒運行。
在這裡我們用一段簡單的程式碼來示範:
@Slf4j public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); new Thread(() -> { log.info("hello this is thread one"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread two"); countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread three"); countDownLatch.countDown(); }).start(); countDownLatch.await(); log.info("say good bye!"); } }
由上面的程式碼可見,我們建立了一個CountDownLatch
計數器為3和三個執行緒同步運行。在main主執行緒中呼叫了countDownLatch.await()
方法使主執行緒進入阻塞。其中三個執行緒任務執行完畢後都會呼叫countDownLatch.countDown()
方法對計數器進行遞減,當三個執行緒任務都執行完畢後計數器計數值為0時主執行緒被喚醒。
註:在建立
CountDownLatch
實例時必須定義計數器值,一般相對較合理的用法是該值的定義需要經過合理的計算使計數值與需要並行的執行緒數相等,在每個執行緒執行完成後做計數遞減,最終喚醒主執行緒繼續執行。
CountDownLatch
計數值設定大於執行緒數,那麼最終所有執行緒都執行完了,而計數為遞減到0那麼主執行緒將會一直處於等待狀態。
CountDownLatch
計數值設定小於並發執行緒數,那麼可能在部分執行緒未執行完畢時,計數就已經遞減到0,則主執行緒會被提前喚醒。
如下圖,主執行緒阻塞與喚醒的核心就是計數器,只有當所有執行緒執行完成計數逐一遞減最終才會喚起 await()
阻塞中的主線程。
註:
await()
可以阻塞一個線程,也可以阻塞多個線程,如果是阻塞多個線程,那麼在計數為0時將會喚醒所有被阻塞的執行緒。
在簡單了解完CountDownLatch
的作用後,相信各位最終目的還是想了解如何去使用,在哪些場景下使用比較合適,接下來我就拿一個對帳業務的場景詳細分析一下。
在目前的情況下,許多平台會與銀聯、微信、支付寶等支付管道對接交易,因此無法避免進行對接。對帳通常都會在每日的凌晨去處理,一方面是凌晨時間點多數平台訪問量都會較小,伺服器壓力也比較輕鬆,而且此時出帳也比較合理,所以在這個時間點做對帳也是一個大數據量計算的操作。
上面講這麼多好像都沒說到重點,在處理對帳之前首先我們肯定是需要透過各個支付管道取得對帳單文件,那麼該如何操作呢?
對帳檔案下載(第一階段):在這種情況下可以設計三個任務並發去取得對帳文件,使用CountDownLatch
阻塞主線程,等待三個任務都取得到檔案的時候做計數遞減,最終喚醒主線將標記本階段處理完成,並發起進入下一階段的通知。
對帳檔案解析(第二階段):在上個階段已下載完成的檔案檔案中,此階段要做的就是解析檔案。由於三個頻道都是不同的廠商那麼文件的內容格式肯定都是不一樣的,這時候我們又可以使用CountDownLatch
啟動三個線程分別去解析各自的對賬文件,最終將文件內容轉換為業務所需的資料統一格式入庫,在三個任務都入庫完成後主執行緒又被喚醒標記完成後,通知下一階段開始進入工作。
對帳結算(第三階段):在上一階段的資料入庫完成後,此階段要做的就是比對每一筆交易是否準確,一般都是以單號與交易管道比對交易的金額是否一致,如果金額一致則該筆交易結算成功,否則將交易判定為異常交易,併入庫處理。由上面的流程分析我們就可以設計相對合理的CountDownLatch
計數,結合Semaphore
信號量控制並發量同時對對比交易單做並發處理,最終帶所有交易單處理完成後喚醒主執行緒標記對帳完成,並通知下一階段進行出帳。
出帳(第四階段):通常平台在對帳完成後會進行出賬,也就是依照平台的業務規則出具相關的帳單方便財務人員進行統計。
以上是Java多執行緒同步工具類別CountDownLatch怎麼使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!