詳解Java中CountDownLatch的用法
CountDownLatch使用場(chǎng)景
線(xiàn)程計(jì)數(shù)器 用于線(xiàn)程執(zhí)行任務(wù),計(jì)數(shù) 等待線(xiàn)程結(jié)束
用法一: 等待所有的事情都做完
//程序計(jì)數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(10000); //2個(gè)線(xiàn)程 ExecutorService executorService = Executors.newFixedThreadPool(2); AtomicInteger count = new AtomicInteger(0); for (int i = 0; i < 10000; i++) { executorService.submit(() -> { count.getAndIncrement();//自增 System.out.println(Thread.currentThread().getName() + " : " + count.get()); countDownLatch.countDown(); }); } //線(xiàn)程池 等待10s executorService.awaitTermination(10, TimeUnit.SECONDS); //關(guān)閉線(xiàn)程 其實(shí)是將線(xiàn)程狀態(tài)設(shè)置為中斷標(biāo)志 必須等待所有線(xiàn)程處理完任務(wù),才能完全關(guān)閉 executorService.shutdown(); //必須等待兩個(gè)線(xiàn)程執(zhí)行完 會(huì)一直等待下去,當(dāng)然也可以設(shè)置指定時(shí)間等待超時(shí) await(timeout); countDownLatch.await(); }
始終是2個(gè)線(xiàn)程在做事情,等2個(gè)線(xiàn)程做完事情才會(huì)停止下來(lái)。
用法二:假設(shè)2個(gè)線(xiàn)程做事情,剛開(kāi)始并行做事情,等一個(gè)執(zhí)行完成之后,另一個(gè)才能執(zhí)行(實(shí)際還是計(jì)數(shù))
//程序計(jì)數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(1); Thread thread1 =new Thread(()->{ System.out.println(" ---------------- 1 準(zhǔn)備 ---------------- "); try { countDownLatch.await(); System.out.println(" ---------------- 1 finsh ---------------- "); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); Thread thread2 = new Thread(() -> { System.out.println(" ---------------- 2 準(zhǔn)備 ---------------- "); try { Thread.sleep(1_000); System.out.println(" ---------------- 異步做事情 ---------------- "); } catch (InterruptedException e) { e.printStackTrace(); }finally { countDownLatch.countDown(); } }); thread2.start(); //main 在等main 結(jié)束 死循環(huán) Thread.currentThread().join();
剛開(kāi)始一起在準(zhǔn)備狀態(tài),然后分開(kāi)做事情
用法三:退出條件
中斷一個(gè)線(xiàn)程 count 到0
//程序計(jì)數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(1); Thread thread = Thread.currentThread(); Thread thread1 = new Thread(() -> { try { Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } // 1 中斷條件1 countDownLatch.countDown(); }); thread1.start(); countDownLatch.await(); System.out.println(" ----------------- "); }
等待時(shí)間中斷
//程序計(jì)數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(1); Thread thread = Thread.currentThread(); Thread thread1 = new Thread(() -> { try { Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); //2 中斷條件3 countDownLatch.await(5, TimeUnit.SECONDS); System.out.println(" ----------------- "); }
就中斷條件而言: 當(dāng)前還可以父線(xiàn)程中斷
//程序計(jì)數(shù)器 Thread thread1 = new Thread(() -> { try { Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } // 中斷條件3 thread.interrupt(); }); thread1.start(); System.out.println(" ----------------- ");
用法四: 封裝結(jié)束完后通知事件
封裝結(jié)束完后通知事件 參考 CyclicBarrier 通知
public class CountDownLatchTest4 extends CountDownLatch { private Runnable runnable; public CountDownLatchTest4(int count, Runnable runnable) { super(count); this.runnable = runnable; } @Override public void countDown() { super.countDown(); if (super.getCount()==0){ runnable.run(); } } public static void main(String[] args) throws InterruptedException { //程序計(jì)數(shù)器 CountDownLatchTest4 countDownLatch = new CountDownLatchTest4(1,()->{ System.out.println(" 計(jì)數(shù)結(jié)束 .... "); }); Thread thread1 = new Thread(() -> { try { Thread.sleep(2_000); countDownLatch.countDown(); System.out.println(" thread 1 do something "); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread thread2 = new Thread(() -> { try { Thread.sleep(1_000); System.out.println(" thread 2 do something "); countDownLatch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); thread2.start(); countDownLatch.await(); System.out.println(" ----------------- main 結(jié)束 ----------------- "); } }
可以看到運(yùn)行結(jié)束,通知事件
自定義計(jì)數(shù)器
當(dāng)然我們也可以實(shí)現(xiàn)自己的計(jì)數(shù)器
/** * 自定義 CountDown 計(jì)數(shù)器 */ public class CountDown { //計(jì)數(shù)器 private int count = 0; private final int total; public CountDown(int total) { this.total = total; } public void countDown() { synchronized (this) { this.count++; //鎖住 ++ 通知其他線(xiàn)程 this.notifyAll(); } } public void aWait() throws InterruptedException { synchronized (this) { while (total != count) { //不等于 則 繼續(xù)等待 this.wait(); } } } }
測(cè)試
CountDown countDown = new CountDown( 5); System.out.println(" 準(zhǔn)備多線(xiàn)程處理任務(wù) "); IntStream.rangeClosed(1, 5).forEach(x -> { new Thread(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(" 線(xiàn)程開(kāi)始 ----- " + Thread.currentThread().getName()); countDown.countDown(); }, x + "").start(); }); try { countDown.aWait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(" 準(zhǔn)備多線(xiàn)程處理任務(wù) 結(jié)束 "); System.out.println(" ---------------------- "); System.out.println(" 結(jié)束 mian ---------- "); }
測(cè)試結(jié)果
最后
CountDownLatch 可以用來(lái)計(jì)數(shù),可以測(cè)試任務(wù)是否執(zhí)行結(jié)束
也可以用來(lái)停止一個(gè)線(xiàn)程,也可以用來(lái)線(xiàn)程運(yùn)行結(jié)束完后通知事件,彼此工作的線(xiàn)程互相獨(dú)立不關(guān)心。
到此這篇關(guān)于詳解Java中CountDownLatch的用法的文章就介紹到這了,更多相關(guān)Java CountDownLatch內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
如何利用Stream改變list中特定對(duì)象的某一屬性
這篇文章主要介紹了如何利用Stream改變list中特定對(duì)象的某一屬性問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12使用Java8進(jìn)行分組(多個(gè)字段的組合分組)
本文主要介紹了使用Java8進(jìn)行分組(多個(gè)字段的組合分組),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Java 帶參數(shù)與帶返回值的方法的定義和調(diào)用
在java中,方法就是用來(lái)完成解決某件事情或?qū)崿F(xiàn)某個(gè)功能的辦法。方法實(shí)現(xiàn)的過(guò)程中,會(huì)包含很多條語(yǔ)句用于完成某些有意義的功能——通常是處理文本,控制輸入或計(jì)算數(shù)值,這篇文章我們來(lái)探究一下帶參數(shù)與帶返回值的方法的定義和調(diào)用2022-04-04java 內(nèi)部類(lèi)(匿名類(lèi),匿名對(duì)象,靜態(tài)內(nèi)部類(lèi))詳解及實(shí)例
這篇文章主要介紹了java 內(nèi)部類(lèi)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-12-12SpringCloud通過(guò)Feign傳遞List類(lèi)型參數(shù)方式
這篇文章主要介紹了SpringCloud通過(guò)Feign傳遞List類(lèi)型參數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java 實(shí)戰(zhàn)項(xiàng)目錘煉之樸素風(fēng)格個(gè)人博客系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+vue+Springboot+ssm+mysql+maven+redis實(shí)現(xiàn)一個(gè)樸素風(fēng)格的個(gè)人博客系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11BCryptPasswordEncoder加密與MD5加密的區(qū)別及說(shuō)明
這篇文章主要介紹了BCryptPasswordEncoder加密與MD5加密的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08