<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java高并發(fā)編程基礎(chǔ)三大利器之CountDownLatch

          共 9817字,需瀏覽 20分鐘

           ·

          2021-10-21 03:08

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


          作者丨Java金融

          來(lái)源丨java金融

          什么是CountDownLatch

          CountDownLatch是通過(guò)一個(gè)計(jì)數(shù)器來(lái)實(shí)現(xiàn)的,計(jì)數(shù)器的初始值是線程的數(shù)量。每當(dāng)一個(gè)線程執(zhí)行完畢后,計(jì)數(shù)器的值就減1,當(dāng)計(jì)數(shù)器的值為0時(shí),表示所有線程都執(zhí)行完畢,然后在閉鎖上(調(diào)用await方法的線程)等待的線程就可以恢復(fù)工作了。

          應(yīng)用場(chǎng)景

          CountDownLatch可以用來(lái)干什么呢?有什么應(yīng)用場(chǎng)景?實(shí)際項(xiàng)目中有應(yīng)用的場(chǎng)景嗎?這應(yīng)該才是大家比較關(guān)心的。我們先來(lái)看看官網(wǎng)提供的例子是如何進(jìn)行應(yīng)用的https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html 官方提供了兩個(gè)demo我直接把它轉(zhuǎn)成了圖片順帶推薦下這個(gè)代碼轉(zhuǎn)圖片的網(wǎng)址https://www.dute.org/code-snapshot 還挺好用的。

          官網(wǎng)demo1

          The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed; The second is a completion signal that allows the driver to wait until all workers have completed.

          • 第一個(gè)開(kāi)始信號(hào)(startSignal)會(huì)阻止任何工人(worker )開(kāi)始工作,在司機(jī)到來(lái)之前。說(shuō)白了就是司機(jī)沒(méi)來(lái)工人就不能干活。
          • 第二個(gè)是完成信號(hào) (doneSignal),允許司機(jī) Driver 等待,直到所有的工人完成.說(shuō)白了就是司機(jī)要等到所有工人完工為止。

          官網(wǎng)demo2

          Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await.

          另一種典型的用法就是把一個(gè)大任務(wù)拆分N個(gè)部分,讓多個(gè)線程(Worker)執(zhí)行,每個(gè)線程(Worker)執(zhí)行完自己的部分計(jì)數(shù)器就減1,當(dāng)所有子部分都完成后,Driver 才繼續(xù)向下執(zhí)行才繼續(xù)執(zhí)行。就好比富士康手機(jī)加工的流水線一樣,組裝一步手機(jī)需要一條條的流水線來(lái)相互配合完成。一條條流水線(Worker),每條線都干自己的活。有的流水線是貼膜的,有的流水線是打螺絲的,有的流水線是質(zhì)檢的、有的流水線充電的、有的流水線貼膜的。等這些流水線都干完了就把一部手機(jī)組裝完成了。

          上面兩個(gè)就是官方提供的demo,下面我再來(lái)兩個(gè)我們平時(shí)開(kāi)發(fā)中可以用到的栗子:

          多個(gè)線程等待:模擬并發(fā),讓并發(fā)線程一起執(zhí)行。

          有時(shí)候我們寫(xiě)了接口想去壓測(cè)下它,看看它的最大并發(fā)數(shù)大概是多少。當(dāng)然我們可以使用Jmeter來(lái)進(jìn)行壓測(cè),但是有時(shí)候我們不想去下載工具,其實(shí)就可以借助CountDownLatch來(lái)實(shí)現(xiàn)。

          /**
           * @author: 公眾號(hào):java金融
           */

          public class TestCountDownLatch1 {
               public static void main(String[] args) throws InterruptedException {
                    CountDownLatch countDownLatch = new CountDownLatch(1);
                    for (int i = 0; i < 5; i++) {
                         new Thread(() -> {
                              try {
                                   //所有請(qǐng)求都阻塞在這,等待
                                   countDownLatch.await();
                                   // 調(diào)用測(cè)試接口
                                   System.out.println(Thread.currentThread().getName() + "開(kāi)始執(zhí)行……");
                              } catch (InterruptedException e) {
                                   e.printStackTrace();
                              }
                         }).start();
                    }
                    // 讓請(qǐng)求都準(zhǔn)備好
                    Thread.sleep(2000);
                    // 讓所有請(qǐng)求統(tǒng)一請(qǐng)求
                    countDownLatch.countDown();
               }
          }

          我們通過(guò)CountDownLatch.await(),讓多個(gè)參與者線程啟動(dòng)后阻塞等待,然后在主線程 調(diào)用CountDownLatch.countdown() 將計(jì)數(shù)減為0,讓所有線程一起往下執(zhí)行;以此實(shí)現(xiàn)了多個(gè)線程在同一時(shí)刻并發(fā)執(zhí)行,來(lái)模擬并發(fā)請(qǐng)求的目的。

          單個(gè)線程等待:多個(gè)線程(任務(wù))完成后,進(jìn)行匯總合并

          /**
           * @author: 公眾號(hào):java金融
           */

          public class TestCountDownLatch1 {
               public static void main(String[] args) throws InterruptedException {
                    int count = 3;
                    CountDownLatch countDownLatch = new CountDownLatch(count);
                    for (int i = 0; i < count; i++) {
                         final int index = i;
                         new Thread(() -> {
                              try {
                                   Thread.sleep(1000 + ThreadLocalRandom.current().nextInt(1000));
                                   System.out.println("finish" + index + Thread.currentThread().getName());
                              } catch (InterruptedException e) {
                                   e.printStackTrace();
                              }finally{
                                  countDownLatch.countDown();
                              }
                         }).start();
                    }
                    countDownLatch.await();// 主線程在阻塞,當(dāng)計(jì)數(shù)器==0,就喚醒主線程往下執(zhí)行。
                    System.out.println("主線程:在所有任務(wù)運(yùn)行完成后,進(jìn)行結(jié)果匯總");
               }
          }

          這種場(chǎng)景應(yīng)該是用的最多了,比如我們打開(kāi)一個(gè)電商的個(gè)人中心頁(yè)面,我們需要調(diào)用,用戶信息接口、用戶訂單接口、用戶會(huì)員信息等接口,然后合并后一起給到前端,假設(shè)每個(gè)接口最長(zhǎng)耗時(shí)為1s,如果我們同步調(diào)用的話最大耗時(shí)時(shí)間是3s,如果我們采用異步調(diào)用然后合并結(jié)果,所以最大的耗時(shí)時(shí)間是3s。每個(gè)接口調(diào)用返回?cái)?shù)據(jù)后調(diào)用countDown方法,讓計(jì)數(shù)器進(jìn)行減1,當(dāng)把計(jì)數(shù)器減為0時(shí)的這個(gè)線程會(huì)去喚醒主線程,讓它繼續(xù)往下走。

          CountDownLatch 實(shí)現(xiàn)原理

          CountDownLatch是通過(guò)AQSstate字段來(lái)實(shí)現(xiàn)的一個(gè)計(jì)數(shù)器,計(jì)數(shù)器的初始值(state的值)為new CountDownLatch設(shè)置的數(shù)量,每次調(diào)用countDown的時(shí)候,state的值會(huì)進(jìn)行減1,最后某個(gè)線程將state值減為0時(shí),會(huì)把調(diào)用了await()進(jìn)行阻塞等待的線程進(jìn)行喚醒。CountDownLatch重寫(xiě)了tryReleaseShared這個(gè)方法,只有當(dāng)state這個(gè)字段被設(shè)置為0時(shí),也就是tryReleaseShared返回true的情況就會(huì)執(zhí)行doReleaseShared方法,把調(diào)用了await的線程進(jìn)行喚醒。

            public final boolean releaseShared(int arg) {
                  if (tryReleaseShared(arg)) {
                      doReleaseShared();
                      return true;
                  }
                  return false;
              }
           protected boolean tryReleaseShared(int releases) {
                      // Decrement count; signal when transition to zero
                      for (;;) {
                          int c = getState();
                          if (c == 0)
                              return false;
                          int nextc = c-1;
                          if (compareAndSetState(c, nextc))
                              return nextc == 0;
                      }
                  }

          CountDownLatch的其他源碼就不進(jìn)行分析了, 相信看了這兩篇文章《Java高并發(fā)編程基礎(chǔ)之AQS》《Java高并發(fā)編程基礎(chǔ)三大利器之Semaphore》再來(lái)看這個(gè)還是比較輕松的。

          總結(jié)

          • CountDownLatch不能重新初始化或者修改CountDownLatch內(nèi)部計(jì)數(shù)器的值。
          • CountDownLatchSemaphore在使用AQS的方式上很相似,在同步狀態(tài)中都是保存的是當(dāng)前的計(jì)數(shù)值。
          • CountDownLatch的作用就是允許一個(gè)或多個(gè)線程等待其他線程完成操作,看起來(lái)有點(diǎn)類(lèi)似join() 方法,但其提供了比 join() 更加靈活的API。
          • CountDownLatch可以手動(dòng)控制在n個(gè)線程里調(diào)用ncountDown()方法使計(jì)數(shù)器進(jìn)行減一操作,也可以在一個(gè)線程里調(diào)用n次執(zhí)行減一操作。
          • join() 的實(shí)現(xiàn)原理是不停檢查join線程是否存活,如果 join 線程存活則讓當(dāng)前線程永遠(yuǎn)等待。所以?xún)烧咧g相對(duì)來(lái)說(shuō)還是CountDownLatch使用起來(lái)較為靈活。

          結(jié)束

          • 由于自己才疏學(xué)淺,難免會(huì)有紕漏,假如你發(fā)現(xiàn)了錯(cuò)誤的地方,還望留言給我指出來(lái),我會(huì)對(duì)其加以修正。
          • 如果你覺(jué)得文章還不錯(cuò),你的轉(zhuǎn)發(fā)、分享、贊賞、點(diǎn)贊、留言就是對(duì)我最大的鼓勵(lì)。
          • 感謝您的閱讀,十分歡迎并感謝您的關(guān)注。

          站在巨人的肩膀上摘蘋(píng)果:

          https://javajr.cn/ https://zhuanlan.zhihu.com/p/148231820


          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤(pán)了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 21
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美性爱精品在线 | 婷婷色色网 | www黄片 | 尻屄视频免费网站 | 99视频在线免费观看视频 |