最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java并發(fā)實例之CyclicBarrier的使用

 更新時間:2017年11月15日 12:00:25   作者:生活半篇記  
這篇文章主要介紹了Java并發(fā)實例之CyclicBarrier的使用,涉及CyclicBarrier的介紹,以及相關(guān)的并發(fā)實例,具有一定參考價值,需要的朋友可以了解下。

最近一直整并發(fā)這塊東西,順便寫點Java并發(fā)的例子,給大家做個分享,也強化下自己記憶,如果有什么錯誤或者不當?shù)牡胤剑瑲g迎大家斧正。

CyclicBarrier是一種多線程并發(fā)控制實用工具,和CountDownLatch非常類似,它也可以實現(xiàn)線程間的計數(shù)等待,但是它的功能比CountDownLatch更加復雜且強大。

CyclicBarrier的介紹

CyclicBarrier 的字面意思是可循環(huán)(Cyclic)使用的屏障(Barrier)。它要做的事情是,讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最后一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續(xù)干活。線程進入屏障通過CyclicBarrier的await()方法。

CyclicBarrier默認的構(gòu)造方法是CyclicBarrier(int parties),其參數(shù)表示屏障攔截的線程數(shù)量,每個線程調(diào)用await方法告訴CyclicBarrier我已經(jīng)到達了屏障,然后當前線程被阻塞。

CyclicBarrier還提供一個更高級的構(gòu)造函數(shù)CyclicBarrier(int parties, Runnable barrierAction),用于在線程到達屏障時,優(yōu)先執(zhí)行barrierAction這個Runnable對象,方便處理更復雜的業(yè)務(wù)場景。

public CyclicBarrier(int parties) {
  this(parties, null);
}
public int getParties() {
  return parties;
}

實現(xiàn)原理:在CyclicBarrier的內(nèi)部定義了一個Lock對象,每當一個線程調(diào)用CyclicBarrier的await方法時,將剩余攔截的線程數(shù)減1,然后判斷剩余攔截數(shù)是否為0,如果不是,進入Lock對象的條件隊列等待。如果是,執(zhí)行barrierAction對象的Runnable方法,然后將鎖的條件隊列中的所有線程放入鎖等待隊列中,這些線程會依次的獲取鎖、釋放鎖,接著先從await方法返回,再從CyclicBarrier的await方法中返回。

CyclicBarrier主要用于一組線程之間的相互等待,而CountDownLatch一般用于一組線程等待另一組些線程。實際上可以通過CountDownLatch的countDown()和await()來實現(xiàn)CyclicBarrier的功能。即 CountDownLatch中的countDown()+await() = CyclicBarrier中的await()。注意:在一個線程中先調(diào)用countDown(),然后調(diào)用await()。

構(gòu)造函數(shù)CyclicBarrier可以理解為循環(huán)柵欄,這個計數(shù)器可以反復使用。比如,假設(shè)我們將計數(shù)器設(shè)置為10,那么湊齊第一批10個線程后,計數(shù)器就會歸零,然后接著湊齊下一批10個線程,這就是它的內(nèi)在含義。

LOL和王者榮耀的玩家很多,許多人應(yīng)該都有打大龍的經(jīng)歷,話說前期大家打算一起去偷大龍,由于前期大家都比較弱,需要五個人都齊了才能打大龍,這樣程序該如何實現(xiàn)呢?本人很菜,開始我的代碼是這么寫的(哈哈大家不要糾結(jié)我的時間):

public class KillDragon {
	/**
   * 模擬打野去打大龍
   */
	public static void dayePlayDragon(){
		System.out.println("打野在去打大龍的路上,需要10s");
	}
	/**
   * 模擬上單去打大龍
   */
	public static void shangdanPlayDragon(){
		System.out.println("上單在去打大龍的路上,需要10s");
	}
	/**
   * 模擬中單去打大龍
   */
	public static void zhongdanPlayDragon(){
		System.out.println("中單在去打大龍的路上,需要10s");
	}
	/**
   * 模擬ADC和輔助去打大龍
   */
	public static void adcAndFuzhuPlayDragon(){
		System.out.println("ADC和輔助在去打大龍的路上,需要10s");
	}
	/**
   * 模擬大家一起去打大龍
   */
	public static void killDragon()
	  {
		System.out.println("打大龍...");
	}
	public static void main(String[] args)
	  {
		dayePlayDragon();
		shangdanPlayDragon();
		zhongdanPlayDragon();
		adcAndFuzhuPlayDragon();
		killDragon();
	}

結(jié)果如下:

打野在去打大龍的路上,需要10s
上單在去打大龍的路上,需要10s
中單在去打大龍的路上,需要10s
ADC和輔助在去打大龍的路上,需要10s
打大龍...

 這完了,大家在路上的時間就花了40s了,顯然是錯誤的。要是都這么干,對方把你塔都要偷光了。不行得改進下,怎么改呢,多線程并發(fā)執(zhí)行,如是我改成了下面這樣的,用volatile關(guān)鍵字。

private static volatile int i = 4;
  public static void main(String[] args) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        long start = System.currentTimeMillis();
        while (i!=0){

        }
        while (i==0) {
          killDragon();
          i--;
          long t = System.currentTimeMillis() - start;
          System.out.println("總共耗時:"+t+"毫秒");
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        dayePlayDragon();
        try {
          Thread.sleep(10000);
          i--;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        shangdanPlayDragon();
        try {
          Thread.sleep(10000);
          i--;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        zhongdanPlayDragon();
        try {
          Thread.sleep(10000);
          i--;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        adcAndFuzhuPlayDragon();
        try {
          Thread.sleep(10000);
          i--;
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }).start();
  }

結(jié)果如下:

打野在去打大龍的路上,需要10s
上單在去打大龍的路上,需要10s
中單在去打大龍的路上,需要10s
ADC和輔助在去打大龍的路上,需要10s
打大龍...
總共耗時:10005毫秒

結(jié)果似乎還不錯,但是處理起來實在是有點麻煩,需要 while (i!=0)一直在那循環(huán)著。這時候?qū)W到了用 CyclicBarrier來處理,代碼如下:

public static void main(String[] args) {
    CyclicBarrier barrier = new CyclicBarrier(5);
    new Thread(new Runnable() {
      @Override
      public void run() {
        long start = System.currentTimeMillis();
        try {
          barrier.await();
        } catch (InterruptedException e) {
          e.printStackTrace();
        } catch (BrokenBarrierException e) {
          e.printStackTrace();
        }
        killDragon();
        long t = System.currentTimeMillis() - start;
        System.out.println("總共耗時:"+t+"毫秒");
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        dayePlayDragon();
        try {
          Thread.sleep(10000);
          barrier.await();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        shangdanPlayDragon();
        try {
          Thread.sleep(10000);
          barrier.await();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        zhongdanPlayDragon();
        try {
          Thread.sleep(10000);
          barrier.await();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }).start();
    new Thread(new Runnable() {
      @Override
      public void run() {
        adcAndFuzhuPlayDragon();
        try {
          Thread.sleep(10000);
          barrier.await();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }).start();
  }

大家都沒到達之前都等待,結(jié)果如下:

打野在去打大龍的路上,需要10s
上單在去打大龍的路上,需要10s
中單在去打大龍的路上,需要10s
ADC和輔助在去打大龍的路上,需要10s
打大龍...
總共耗時:10002毫秒

CyclicBarrier相當于線程的計數(shù)器:

CyclicBarrier初始化時規(guī)定一個數(shù)目,然后計算調(diào)用了CyclicBarrier.await()進入等待的線程數(shù)。當線程數(shù)達到了這個數(shù)目時,所有進入等待狀態(tài)的線程被喚醒并繼續(xù)。

CyclicBarrier就象它名字的意思一樣,可看成是個障礙, 所有的線程必須到齊后才能一起通過這個障礙。

CyclicBarrier初始時還可帶一個Runnable的參數(shù), 此Runnable任務(wù)在CyclicBarrier的數(shù)目達到后,所有其它線程被喚醒前被執(zhí)行。

當然這樣使用CyclicBarrier和使用CountDownLatch是沒什么區(qū)別的,正如前文所說的CyclicBarrier的功能更加的復雜且強大。給大家看一個《實戰(zhàn)Java高并發(fā)程序設(shè)計》一書上的一個例子。

比如:司令下達命令,要求10個士兵去一起完成一項任務(wù)。這時,就會要求10個士兵先集合報道,接著,一起雄赳赳氣昂昂地去執(zhí)行任務(wù)。當10個士兵都執(zhí)行完了任務(wù),那么司機就可以對外宣稱,任務(wù)完成。相比CountDownLatch,CyclicBarrier可以接受一個參數(shù)作為BarrierAction。所謂的BarrierAction就是當計數(shù)器一次計數(shù)完成后,系統(tǒng)會執(zhí)行的動作。如下構(gòu)造函數(shù),其中,parties表示技術(shù)總數(shù),也就是參與的線程總數(shù)。

public CyclicBarrier(int parties, Runnable barrierAction)

下面示例演示了上述任務(wù)場景

public class CyclicBarrierDemo {
  public static class Soldier implements Runnable {
    private String soldier;
    private final CyclicBarrier cyclicBarrier;
    public Soldier(CyclicBarrier cyclicBarrier, String soldier) {
      this.soldier = soldier;
      this.cyclicBarrier = cyclicBarrier;
    }
    @Override
    public void run() {
      try {
        cyclicBarrier.await();
        doWork();
        cyclicBarrier.await();
      } catch (InterruptedException e) {
        e.printStackTrace();
      } catch (BrokenBarrierException e) {
        e.printStackTrace();
      }
    }
    void doWork() {
      try {
        Thread.sleep(Math.abs(new Random().nextInt() % 10000));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(soldier + ":任務(wù)完成");
    }
  }
  public static class BarrierRun implements Runnable {
    boolean flag;
    int N;
    public BarrierRun(boolean flag, int N) {
      this.flag = flag;
      this.N = N;
    }
    @Override
    public void run() {
      if (flag) {
        System.out.println("司令:[士兵" + N + "個,任務(wù)完成!");
      } else {
        System.out.println("司令:[士兵" + N + "個,集合完畢!");
        flag = true;
      }
    }
  }
  public static void main(String args[]) {
    final int N = 10;
    Thread[] allSoldier = new Thread[N];
    boolean flag = false;
    CyclicBarrier cyclicBarrier = new CyclicBarrier(N, new BarrierRun(flag, N));
    System.out.println("集合隊伍!");
    for (int i = 0; i < N; i++) {
      System.out.println("士兵" + i + "報道!");
      allSoldier[i] = new Thread(new Soldier(cyclicBarrier, "士兵" + i));
      allSoldier[i].start();
    }
  }
}

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

集合隊伍!
士兵0報道!
士兵1報道!
士兵2報道!
士兵3報道!
士兵4報道!
士兵5報道!
士兵6報道!
士兵7報道!
士兵8報道!
士兵9報道!
司令:[士兵10個,集合完畢!
士兵0:任務(wù)完成
士兵2:任務(wù)完成
士兵9:任務(wù)完成
士兵3:任務(wù)完成
士兵7:任務(wù)完成
士兵8:任務(wù)完成
士兵1:任務(wù)完成
士兵4:任務(wù)完成
士兵5:任務(wù)完成
士兵6:任務(wù)完成
司令:[士兵10個,任務(wù)完成!

總結(jié)

以上就是本文關(guān)于Java并發(fā)實例之CyclicBarrier的使用的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:

Javaweb應(yīng)用使用限流處理大量的并發(fā)請求詳解

java并發(fā)學習之BlockingQueue實現(xiàn)生產(chǎn)者消費者詳解

Java系統(tǒng)的高并發(fā)解決方法詳解

如有不足之處,歡迎留言指出。期待您的寶貴意見!

相關(guān)文章

  • java中的自增問題介紹

    java中的自增問題介紹

    下面小編就為大家?guī)硪黄猨ava中的自增問題介紹。小編覺得挺不錯的,現(xiàn)在分享給大家。給大家一個參考。
    2016-03-03
  • Java 反射機制實例詳解

    Java 反射機制實例詳解

    這篇文章主要介紹了Java 反射機制實例詳解的相關(guān)資料,這里對java中反射機制進行了詳細的分析,需要的朋友可以參考下
    2017-09-09
  • JAVA中split函數(shù)的常見用法實例

    JAVA中split函數(shù)的常見用法實例

    Java中我們可以利用split把字符串按照指定的分割符進行分割,然后返回字符串數(shù)組,下面這篇文章主要給大家介紹了關(guān)于JAVA中split函數(shù)的常見用法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-07-07
  • SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務(wù)端)

    SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務(wù)端)

    這篇文章主要介紹了SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務(wù)端),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 使用@PathVariable時候無法將參數(shù)映射到變量中的解決

    使用@PathVariable時候無法將參數(shù)映射到變量中的解決

    這篇文章主要介紹了使用@PathVariable時候無法將參數(shù)映射到變量中的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Spring創(chuàng)建Bean的過程Debug的詳細流程

    Spring創(chuàng)建Bean的過程Debug的詳細流程

    這篇文章主要介紹了Spring創(chuàng)建Bean的過程Debug的流程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • Java實現(xiàn)撲克牌游戲的示例代碼

    Java實現(xiàn)撲克牌游戲的示例代碼

    想不想帶上好朋友來上一局三人撲克呢?這篇文章教你如何利用Java語言實現(xiàn)一個簡單的撲克牌游戲,文中的示例代碼講解詳細,感興趣的可以了解一下
    2022-09-09
  • 解決SpringBoot整合ElasticSearch遇到的連接問題

    解決SpringBoot整合ElasticSearch遇到的連接問題

    這篇文章主要介紹了解決SpringBoot整合ElasticSearch遇到的連接問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot詳解整合MyBatis過程中可能遇到的問題

    SpringBoot詳解整合MyBatis過程中可能遇到的問題

    因為Spring Boot框架開發(fā)的便利性,所以實現(xiàn)Spring Boot與數(shù)據(jù)訪問層框架(例如MyBatis)的整合非常簡單,主要是引入對應(yīng)的依賴啟動器,并進行數(shù)據(jù)庫相關(guān)參數(shù)設(shè)置即可
    2022-07-07
  • Java之多個線程順序循環(huán)執(zhí)行的幾種實現(xiàn)

    Java之多個線程順序循環(huán)執(zhí)行的幾種實現(xiàn)

    這篇文章主要介紹了Java之多個線程順序循環(huán)執(zhí)行的幾種實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評論

彭州市| 阿拉善右旗| 中宁县| 临猗县| 东兴市| 南宁市| 盐边县| 临武县| 西华县| 蒙城县| 夏津县| 萍乡市| 黎川县| 齐齐哈尔市| 界首市| 铁岭县| 阿瓦提县| 朔州市| 屏东市| 东乡族自治县| 灵石县| 桂林市| 和林格尔县| 安阳市| 石泉县| 象州县| 繁昌县| 凤翔县| 汤阴县| 伊宁县| 淮安市| 南江县| 台湾省| 云霄县| 沙雅县| 宜丰县| 新宾| 香格里拉县| 永定县| 中方县| 遵义县|