JAVA 多線程編程之CountDownLatch使用詳解
CountDownLatch 的基本原理
CountDownLatch 是基于計數(shù)器的原理實現(xiàn)的,它內(nèi)部維護了一個整型的計數(shù)器。創(chuàng)建一個 CountDownLatch 對象時,需要指定一個初始計數(shù)值,該計數(shù)值表示需要等待的線程數(shù)量。每當一個線程完成了其任務,它調(diào)用 CountDownLatch 的 countDown() 方法,計數(shù)器的值就會減一。當計數(shù)器的值變成 0 時,等待的線程就會被喚醒,繼續(xù)執(zhí)行它們的任務。
CountDownLatch 的用法
CountDownLatch 在多線程編程中有廣泛的應用場景,例如主線程等待所有子線程完成任務后再繼續(xù)執(zhí)行,多個線程協(xié)同完成一個任務等。以下是 CountDownLatch 的基本用法:
- 創(chuàng)建 CountDownLatch 對象,并指定初始計數(shù)值。
CountDownLatch latch = new CountDownLatch(3); // 初始計數(shù)值為 3
- 創(chuàng)建需要等待的線程,線程完成任務后調(diào)用 countDown() 方法。
Runnable task = new Runnable() { @Override public void run() { // 線程任務邏輯 // ... latch.countDown(); // 完成任務后調(diào)用 countDown() } };
- 創(chuàng)建等待線程,等待計數(shù)器的值變成 0 后再繼續(xù)執(zhí)行。
try { latch.await(); // 等待計數(shù)器的值變成 0 // 繼續(xù)執(zhí)行需要等待的線程后續(xù)邏輯 } catch (InterruptedException e) { // 處理中斷異常 e.printStackTrace(); }
CountDownLatch 示例
下面通過一個簡單的示例代碼來演示 CountDownLatch 的用法。假設(shè)有一個需求,需要三個工人協(xié)同完成一項任務,主線程需要等待三個工人完成任務后才能繼續(xù)執(zhí)行。示例代碼如下:
import java.util.concurrent.CountDownLatch; public class CountDownLatchExample { public static void main(String[] args) { final int workerCount = 3; final CountDownLatch latch = new CountDownLatch(workerCount); // 創(chuàng)建并啟動三個工人線程 for (int i = 0; i < workerCount; i++) { Worker worker = new Worker(latch, "Worker " + (i + 1)); new Thread(worker).start(); } try { System.out.println("Main thread is waiting for workers to finish..."); latch.await(); // 主線程等待三個工人線程完成任務 System.out.println("All workers have finished, main thread continues..."); } catch (InterruptedException e) { e.printStackTrace(); } } static class Worker implements Runnable { private final CountDownLatch latch; private final String name; public Worker(CountDownLatch latch, String name) { this.latch = latch; this.name = name; } @Override public void run() { System.out.println(name + " starts working..."); // 模擬工作耗時 try { Thread.sleep((long) (Math.random() * 10000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(name + " finishes working."); latch.countDown(); // 工人完成任務后調(diào)用 countDown() } } }
在上述代碼中,首先創(chuàng)建了一個 CountDownLatch 對象,并指定初始計數(shù)值為 3。然后創(chuàng)建了三個工人線程并啟動,每個工人線程模擬完成一項工作后調(diào)用 countDown() 方法,計數(shù)器的值減一。最后,主線程調(diào)用 await() 方法等待計數(shù)器的值變成 0,表示所有工人都完成任務后再繼續(xù)執(zhí)行。
運行該程序后,輸出結(jié)果如下:
Worker 1 starts working...
Worker 2 starts working...
Worker 3 starts working...
Main thread is waiting for workers to finish...
Worker 2 finishes working.
Worker 1 finishes working.
Worker 3 finishes working.
All workers have finished, main thread continues...
可以看到,主線程在三個工人線程完成任務后才繼續(xù)執(zhí)行,并且所有工人線程的完成順序是不確定的,但主線程會一直等待直到所有工人完成任務。
擴展:上面的worker線程運行是沒有順序的,我們可以使用join()來使線程有序等待上一個線程運行結(jié)束。
public static void main(String[] args) throws InterruptedException { final int workerCount = 3; final CountDownLatch latch = new CountDownLatch(workerCount); System.out.println("Main thread is waiting for workers to finish..."); // 創(chuàng)建并啟動三個工人線程 for (int i = 0; i < workerCount; i++) { Worker worker = new Worker(latch, "Worker " + (i + 1)); Thread t = new Thread(worker); t.start(); t.join(); // 等待上一個線程執(zhí)行完成 } try { latch.await(); // 主線程等待三個工人線程完成任務 System.out.println("All workers have finished, main thread continues..."); } catch (InterruptedException e) { e.printStackTrace(); } }
輸出結(jié)果:
Main thread is waiting for workers to finish...
Worker 1 starts working...
Worker 1 finishes working.
Worker 2 starts working...
Worker 2 finishes working.
Worker 3 starts working...
Worker 3 finishes working.
All workers have finished, main thread continues...
CountDownLatch 和 join 的作用和使用方式不同。CountDownLatch 用于等待多個線程完成任務后再繼續(xù)執(zhí)行,而 join 用于等待一個線程執(zhí)行完畢后再繼續(xù)執(zhí)行。另外,CountDownLatch 是基于計數(shù)器的實現(xiàn),可以靈活地控制線程的數(shù)量和完成順序;而 join 方法只能等待單個線程執(zhí)行完畢。
總結(jié)
CountDownLatch 是一個非常實用的線程同步工具,在多線程編程中有著廣泛的應用。它基于計數(shù)器的原理實現(xiàn),通過等待計數(shù)器的值變成 0 來實現(xiàn)線程的同步和協(xié)作。在使用 CountDownLatch 時,需要注意初始計數(shù)值的設(shè)定和 countDown() 和 await() 方法的使用。 本文介紹了 CountDownLatch 的基本原理和用法,并通過示代碼演示了它的使用。希望本文能夠幫助讀者更好地理解和應用 CountDownLatch,在實際的項目中提高多線程編程的效率和質(zhì)量。
以上就是JAVA 多線程編程之CountDownLatch使用詳解的詳細內(nèi)容,更多關(guān)于JAVA CountDownLatch的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何使用Spring?integration在Springboot中集成Mqtt詳解
MQTT是多個客戶端通過一個中央服務器傳遞信息的多對多協(xié)議,能高效地將信息分發(fā)給一個或多個訂閱者,下面這篇文章主要給大家介紹了關(guān)于如何使用Spring?integration在Springboot中集成Mqtt的相關(guān)資料,需要的朋友可以參考下2023-02-02Spring探秘之如何妙用BeanPostProcessor
BeanPostProcessor也稱為Bean后置處理器,它是Spring中定義的接口,在Spring容器的創(chuàng)建過程中會回調(diào)BeanPostProcessor中定義的兩個方法,這篇文章主要給大家介紹了關(guān)于Spring探秘之如何妙用BeanPostProcessor的相關(guān)資料,需要的朋友可以參考下2022-01-01Shiro:自定義Realm實現(xiàn)權(quán)限管理方式
這篇文章主要介紹了Shiro:自定義Realm實現(xiàn)權(quán)限管理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10Java實現(xiàn)的打地鼠小游戲完整示例【附源碼下載】
這篇文章主要介紹了Java實現(xiàn)的打地鼠小游戲,結(jié)合完整實例形式分析了Java多線程操作及鍵盤按鍵響應實現(xiàn)的打地鼠游戲功能相關(guān)操作技巧,需要的朋友可以參考下2018-07-07springboot+mybatis+枚舉處理器的實現(xiàn)
在Spring?boot項目開發(fā)中經(jīng)常遇到需要使用枚舉的場景,本文就介紹了springboot+mybatis+枚舉處理器的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03