<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多線程之CyclicBarrier

          共 3820字,需瀏覽 8分鐘

           ·

          2021-11-30 14:22

          這里就JUC包中的CyclicBarrier類(lèi)做相關(guān)介紹

          abstract.jpeg

          概述

          JUC中的CyclicBarrier類(lèi)是一個(gè)并發(fā)控制工具。其可以使線程在柵欄處進(jìn)行等待。當(dāng)指定數(shù)量的線程全部到達(dá)柵欄處后柵欄才會(huì)打開(kāi),從而使各線程結(jié)束阻塞繼續(xù)向下執(zhí)行。其主要方法如下所示,可以看到在線程全部到達(dá)柵欄時(shí),還可以通過(guò)barrierAction參數(shù)設(shè)置準(zhǔn)備打開(kāi)柵欄前需執(zhí)行的任務(wù)。其中,該任務(wù)由最后一個(gè)到達(dá)柵欄的線程負(fù)責(zé)執(zhí)行。具體地,線程調(diào)用await方法實(shí)現(xiàn)告訴CyclicBarrier自己已經(jīng)到達(dá)柵欄處,并阻塞等待柵欄打開(kāi)

          //?創(chuàng)建一個(gè)指定計(jì)數(shù)器值的CyclicBarrier實(shí)例
          public?CyclicBarrier(int?parties);

          //?創(chuàng)建一個(gè)指定計(jì)數(shù)器值的CyclicBarrier實(shí)例,?并指定柵欄打開(kāi)前需執(zhí)行的任務(wù)
          public?CyclicBarrier(int?parties,?Runnable?barrierAction);

          //?線程阻塞等待柵欄打開(kāi)
          public?int?await()?throws?InterruptedException,?BrokenBarrierException;

          //?支持超時(shí)的await方法
          public?int?await(long?timeout,?TimeUnit?unit)?throws?InterruptedException,?BrokenBarrierException,?TimeoutException;

          //?喚醒其他正在柵欄處被阻塞的線程(即拋出BrokenBarrierException異常),?同時(shí)將CyclicBarrier實(shí)例恢復(fù)為初始化狀態(tài),以便下一次使用
          public?void?reset();

          基本實(shí)踐

          下面即是一個(gè)CyclicBarrier的基本實(shí)踐示例


          public?class?CyclicBarrierTest1?{

          ????private?static?DateTimeFormatter?formatter?=?DateTimeFormatter.ofPattern("HH:mm:ss");

          ????@Test
          ????public?void?test1()?throws?InterruptedException?{
          ????????ExecutorService?threadPool?=?Executors.newFixedThreadPool(10);

          ????????Runnable?initTask?=?()?->?{
          ????????????info("---------------------------------");
          ????????};

          ????????CyclicBarrier?cyclicBarrier?=?new?CyclicBarrier(3,?initTask);

          ????????Stream.of("張三","李四","王二")
          ????????????.map(?name?->?new?PlayGame(name,?cyclicBarrier)?)
          ????????????.forEach(playGame?->?{
          ????????????????threadPool.execute(playGame);
          ????????????}?);

          ????????//?主線程等待所有任務(wù)執(zhí)行完畢
          ????????try{?Thread.sleep(?120*1000?);?}?catch?(Exception?e)?{}
          ????????info("Game?Over");
          ????}

          ????/**
          ?????*?打印信息
          ?????*?@param?msg
          ?????*/

          ????private?static?void?info(String?msg)?{
          ????????String?time?=?formatter.format(LocalTime.now());
          ????????String?threadName?=?Thread.currentThread().getName();
          ????????String?log?=?"["+time+"]?"+?msg+"?<"+threadName+">";
          ????????System.out.println(log);
          ????}

          ????/**
          ?????*?模擬業(yè)務(wù)耗時(shí)
          ?????*/

          ????private?static?void?doSomeWork()?{
          ????????try{
          ????????????Integer?second?=?RandomUtils.nextInt(3,20);
          ????????????System.out.println("second:?"?+?second);
          ????????????Thread.sleep(?second?*?1000?);
          ????????}catch?(Exception?e)?{
          ????????????System.out.println(?"Happen?Exception:?"?+?e.getMessage());
          ????????}
          ????}

          ????@AllArgsConstructor
          ????private?static?class?PlayGame?implements?Runnable{

          ????????private?String?name;

          ????????private?CyclicBarrier?cyclicBarrier;

          ????????@Override
          ????????public?void?run()?{
          ????????????//?模擬業(yè)務(wù)耗時(shí)
          ????????????doSomeWork();
          ????????????info(name?+?"?上線");
          ????????????//?阻塞等待其他玩家上線
          ????????????try{
          ????????????????cyclicBarrier.await();
          ????????????}catch?(Exception?e)?{
          ????????????????System.out.println(?"Happen?Exception:?"?+?e);
          ????????????}

          ????????????info(name?+?"?選擇角色?開(kāi)始");
          ????????????//?模擬業(yè)務(wù)耗時(shí)
          ????????????doSomeWork();
          ????????????info(name?+?"?選擇角色?結(jié)束");
          ????????????//?阻塞等待其他玩家選擇角色
          ????????????try{
          ????????????????cyclicBarrier.await();
          ????????????}catch?(Exception?e)?{
          ????????????????System.out.println(?"Happen?Exception:?"?+?e);
          ????????????}

          ????????????info(name?+?"?開(kāi)始游戲");

          ????????}
          ????}
          }

          從測(cè)試結(jié)果可以看出,當(dāng)用戶 開(kāi)始選擇角色 或 開(kāi)始游戲時(shí),各線程是同時(shí)開(kāi)始的。至此也可以看出其與CountDownLatch的顯著區(qū)別,后者是一次性的,而前者CyclicBarrier則可以重復(fù)使用

          figure 1.jpeg

          基本原理

          通過(guò)上面的代碼示例,可以看到CyclicBarrier與CountDownLatch相比功能很類(lèi)似。只不過(guò)前者可以重復(fù)使用,而后者則是一次性的。但二者在實(shí)現(xiàn)上卻大相徑庭,CountDownLatch是直接基于AQS實(shí)現(xiàn)的。而CyclicBarrier則是利用ReentrantLock、Condition進(jìn)行實(shí)現(xiàn)的。具體地,當(dāng)線程調(diào)用CyclicBarrier的await方法時(shí),如果未達(dá)到指定數(shù)量時(shí),則是通過(guò)Condition條件變量的await方法進(jìn)行阻塞的;如果是最后一個(gè)線程則會(huì)通過(guò)Condition條件變量的signalAll方法來(lái)喚醒所有被阻塞的線程

          與此同時(shí),由于CyclicBarrier是可重復(fù)使用的。故每一輪結(jié)束后,其內(nèi)部會(huì)通過(guò)nextGeneration方法生成所謂的下一代CyclicBarrier。本質(zhì)上相當(dāng)于重新實(shí)例化了一次CyclicBarrier

          Note

          1. 在實(shí)際使用CyclicBarrier過(guò)程中,需要非常小心處理BrokenBarrierException異常。本文示例代碼為了簡(jiǎn)便,故省略了異常處理過(guò)程。因?yàn)榘l(fā)生該異常說(shuō)明柵欄被損壞了。推薦的處理措施有:一方面,調(diào)用CyclicBarrier的reset方法,來(lái)喚醒其他由于調(diào)用await方法而被阻塞的線程以避免一直被阻塞,同時(shí)將CyclicBarrier實(shí)例恢復(fù)至初始化狀態(tài);另一方面,推薦使用具有超時(shí)機(jī)制的await方法,以避免線程被永久性阻塞

          參考文獻(xiàn)

          1. Java并發(fā)編程之美 翟陸續(xù)、薛賓田著
          瀏覽 46
          點(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>
                  亚洲无码成人片 | 日本三级电影片一区二区 | 久久久永久免费视频 | 天天干天天谢天天插 | 成人毛片18女人毛片免费96 |