日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java并发中CountDownLatch的使用

發(fā)布時(shí)間:2024/2/28 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发中CountDownLatch的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 主線程等待子線程全都結(jié)束之后再開(kāi)始運(yùn)行
    • 等待所有線程都準(zhǔn)備好再一起執(zhí)行
    • 停止CountdownLatch的await

java并發(fā)中CountDownLatch的使用

在java并發(fā)中,控制共享變量的訪問(wèn)非常重要,有時(shí)候我們也想控制并發(fā)線程的執(zhí)行順序,比如:等待所有線程都執(zhí)行完畢之后再執(zhí)行另外的線程,或者等所有線程都準(zhǔn)備好了才開(kāi)始所有線程的執(zhí)行等。

這個(gè)時(shí)候我們就可以使用到CountDownLatch。

簡(jiǎn)單點(diǎn)講,CountDownLatch存有一個(gè)放在QueuedSynchronizer中的計(jì)數(shù)器。當(dāng)調(diào)用countdown() 方法時(shí),該計(jì)數(shù)器將會(huì)減一。然后再調(diào)用await()來(lái)等待計(jì)數(shù)器歸零。

private static final class Sync extends AbstractQueuedSynchronizer {... }private final Sync sync;public void countDown() {sync.releaseShared(1);} public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1);}public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}

下面我們舉兩個(gè)使用的例子:

主線程等待子線程全都結(jié)束之后再開(kāi)始運(yùn)行

這里我們定義子線程類,在子線程類里面,我們傳入一個(gè)CountDownLatch用來(lái)計(jì)數(shù),然后在子線程結(jié)束之前,調(diào)用該CountDownLatch的countDown方法。最后在主線程中調(diào)用await()方法來(lái)等待子線程結(jié)束執(zhí)行。

@Slf4j public class MainThreadWaitUsage implements Runnable {private List<String> outputScraper;private CountDownLatch countDownLatch;public MainThreadWaitUsage(List<String> outputScraper, CountDownLatch countDownLatch) {this.outputScraper = outputScraper;this.countDownLatch = countDownLatch;}@Overridepublic void run() {outputScraper.add("Counted down");countDownLatch.countDown();} }

看下怎么調(diào)用:

@Testpublic void testCountDownLatch()throws InterruptedException {List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());CountDownLatch countDownLatch = new CountDownLatch(5);List<Thread> workers = Stream.generate(() -> new Thread(new MainThreadWaitUsage(outputScraper, countDownLatch))).limit(5).collect(toList());workers.forEach(Thread::start);countDownLatch.await();outputScraper.add("Latch released");log.info(outputScraper.toString());}

執(zhí)行結(jié)果如下:

07:37:27.388 [main] INFO MainThreadWaitUsageTest - [Counted down, Counted down, Counted down, Counted down, Counted down, Latch released]

等待所有線程都準(zhǔn)備好再一起執(zhí)行

上面的例子中,我們是主線程等待子線程,那么在這個(gè)例子中,我們將會(huì)看看怎么子線程一起等待到準(zhǔn)備好的狀態(tài),再一起執(zhí)行。

思路也很簡(jiǎn)單,在子線程開(kāi)始之后,將等待的子線程計(jì)數(shù)器減一,在主線程中await該計(jì)數(shù)器,等計(jì)數(shù)器歸零之后,主線程再通知子線程運(yùn)行。

public class ThreadWaitThreadUsage implements Runnable {private List<String> outputScraper;private CountDownLatch readyThreadCounter;private CountDownLatch callingThreadBlocker;private CountDownLatch completedThreadCounter;public ThreadWaitThreadUsage(List<String> outputScraper,CountDownLatch readyThreadCounter,CountDownLatch callingThreadBlocker,CountDownLatch completedThreadCounter) {this.outputScraper = outputScraper;this.readyThreadCounter = readyThreadCounter;this.callingThreadBlocker = callingThreadBlocker;this.completedThreadCounter = completedThreadCounter;}@Overridepublic void run() {readyThreadCounter.countDown();try {callingThreadBlocker.await();outputScraper.add("Counted down");} catch (InterruptedException e) {e.printStackTrace();} finally {completedThreadCounter.countDown();}} }

看下怎么調(diào)用:

@Testpublic void testCountDownLatch()throws InterruptedException {List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());CountDownLatch readyThreadCounter = new CountDownLatch(5);CountDownLatch callingThreadBlocker = new CountDownLatch(1);CountDownLatch completedThreadCounter = new CountDownLatch(5);List<Thread> workers = Stream.generate(() -> new Thread(new ThreadWaitThreadUsage(outputScraper, readyThreadCounter, callingThreadBlocker, completedThreadCounter))).limit(5).collect(toList());workers.forEach(Thread::start);readyThreadCounter.await();outputScraper.add("Workers ready");callingThreadBlocker.countDown();completedThreadCounter.await();outputScraper.add("Workers complete");log.info(outputScraper.toString());}

輸出結(jié)果如下:

07:41:47.861 [main] INFO ThreadWaitThreadUsageTest - [Workers ready, Counted down, Counted down, Counted down, Counted down, Counted down, Workers complete]

停止CountdownLatch的await

如果我們調(diào)用await()方法,該方法將會(huì)等待一直到count=0才結(jié)束。但是如果在線程執(zhí)行過(guò)程中出現(xiàn)了異常,可能導(dǎo)致countdown方法執(zhí)行不了。那么await()方法可能會(huì)出現(xiàn)無(wú)限等待的情況。

這個(gè)時(shí)候我們可以使用:

public boolean await(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}

本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/CountDownLatch

更多精彩內(nèi)容且看:

  • 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
  • Spring Boot 2.X系列教程:七天從無(wú)到有掌握Spring Boot-持續(xù)更新
  • Spring 5.X系列教程:滿足你對(duì)Spring5的一切想象-持續(xù)更新
  • java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程

更多教程請(qǐng)參考 flydean的博客

總結(jié)

以上是生活随笔為你收集整理的java并发中CountDownLatch的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。