詳解Java中CountDownLatch的用法
CountDownLatch使用場景
線程計數(shù)器 用于線程執(zhí)行任務(wù),計數(shù) 等待線程結(jié)束
用法一: 等待所有的事情都做完
//程序計數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(10000); //2個線程 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(); }); } //線程池 等待10s executorService.awaitTermination(10, TimeUnit.SECONDS); //關(guān)閉線程 其實是將線程狀態(tài)設(shè)置為中斷標志 必須等待所有線程處理完任務(wù),才能完全關(guān)閉 executorService.shutdown(); //必須等待兩個線程執(zhí)行完 會一直等待下去,當然也可以設(shè)置指定時間等待超時 await(timeout); countDownLatch.await(); }
始終是2個線程在做事情,等2個線程做完事情才會停止下來。
用法二:假設(shè)2個線程做事情,剛開始并行做事情,等一個執(zhí)行完成之后,另一個才能執(zhí)行(實際還是計數(shù))
//程序計數(shù)器 CountDownLatch countDownLatch = new CountDownLatch(1); Thread thread1 =new Thread(()->{ System.out.println(" ---------------- 1 準備 ---------------- "); try { countDownLatch.await(); System.out.println(" ---------------- 1 finsh ---------------- "); } catch (InterruptedException e) { e.printStackTrace(); } }); thread1.start(); Thread thread2 = new Thread(() -> { System.out.println(" ---------------- 2 準備 ---------------- "); 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();
剛開始一起在準備狀態(tài),然后分開做事情
用法三:退出條件
中斷一個線程 count 到0
//程序計數(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ù)器 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(" ----------------- "); }
就中斷條件而言: 當前還可以父線程中斷
//程序計數(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 { //程序計數(shù)器 CountDownLatchTest4 countDownLatch = new CountDownLatchTest4(1,()->{ System.out.println(" 計數(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é)束 ----------------- "); } }
可以看到運行結(jié)束,通知事件
自定義計數(shù)器
當然我們也可以實現(xiàn)自己的計數(shù)器
/** * 自定義 CountDown 計數(shù)器 */ public class CountDown { //計數(shù)器 private int count = 0; private final int total; public CountDown(int total) { this.total = total; } public void countDown() { synchronized (this) { this.count++; //鎖住 ++ 通知其他線程 this.notifyAll(); } } public void aWait() throws InterruptedException { synchronized (this) { while (total != count) { //不等于 則 繼續(xù)等待 this.wait(); } } } }
測試
CountDown countDown = new CountDown( 5); System.out.println(" 準備多線程處理任務(wù) "); IntStream.rangeClosed(1, 5).forEach(x -> { new Thread(() -> { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(" 線程開始 ----- " + Thread.currentThread().getName()); countDown.countDown(); }, x + "").start(); }); try { countDown.aWait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(" 準備多線程處理任務(wù) 結(jié)束 "); System.out.println(" ---------------------- "); System.out.println(" 結(jié)束 mian ---------- "); }
測試結(jié)果
最后
CountDownLatch 可以用來計數(shù),可以測試任務(wù)是否執(zhí)行結(jié)束
也可以用來停止一個線程,也可以用來線程運行結(jié)束完后通知事件,彼此工作的線程互相獨立不關(guān)心。
到此這篇關(guān)于詳解Java中CountDownLatch的用法的文章就介紹到這了,更多相關(guān)Java CountDownLatch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
Java 帶參數(shù)與帶返回值的方法的定義和調(diào)用
在java中,方法就是用來完成解決某件事情或?qū)崿F(xiàn)某個功能的辦法。方法實現(xiàn)的過程中,會包含很多條語句用于完成某些有意義的功能——通常是處理文本,控制輸入或計算數(shù)值,這篇文章我們來探究一下帶參數(shù)與帶返回值的方法的定義和調(diào)用2022-04-04java 內(nèi)部類(匿名類,匿名對象,靜態(tài)內(nèi)部類)詳解及實例
這篇文章主要介紹了java 內(nèi)部類詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下2016-12-12SpringCloud通過Feign傳遞List類型參數(shù)方式
這篇文章主要介紹了SpringCloud通過Feign傳遞List類型參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Java 實戰(zhàn)項目錘煉之樸素風格個人博客系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+vue+Springboot+ssm+mysql+maven+redis實現(xiàn)一個樸素風格的個人博客系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11BCryptPasswordEncoder加密與MD5加密的區(qū)別及說明
這篇文章主要介紹了BCryptPasswordEncoder加密與MD5加密的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08