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

java多線程開發(fā)之通過對戰(zhàn)游戲?qū)W習(xí)CyclicBarrier

 更新時間:2018年08月31日 08:44:37   作者:云梟zd  
這篇文章給大家分享了關(guān)于java多線程開發(fā)中通過對戰(zhàn)游戲?qū)W習(xí)CyclicBarrier的相關(guān)知識點內(nèi)容,有興趣的朋友們學(xué)習(xí)參考下。

CyclicBarrier是java.util.concurrent包下面的一個工具類,字面意思是可循環(huán)使用(Cyclic)的屏障(Barrier),通過它可以實現(xiàn)讓一組線程到達(dá)一個屏障(也可以叫同步點)時被阻塞,直到最后一個線程到達(dá)屏障時,所有被屏障攔截的線程才會繼續(xù)執(zhí)行。

這篇文章將介紹CyclicBarrier這個同步工具類的以下幾點

  1. 通過案例分析
  2. 兩種不同構(gòu)造函數(shù)測試
  3. CyclicBarrier和CountDownLatch的區(qū)別
  4. await方法及源碼分析。

需求

繼上一篇CountDownLatch模擬游戲加載后,現(xiàn)在用戶點擊開始按鈕后,需要匹配包括自己在內(nèi)的五個玩家才能開始游戲,匹配玩家成功后進(jìn)入到選擇角色階段。當(dāng)5位玩家角色都選擇完畢后,開始進(jìn)入游戲。進(jìn)入游戲時需要加載相關(guān)的數(shù)據(jù),待全部玩家都加載完畢后正式開始游戲。

解決方案

從需求中可以知道,想要開始游戲需要經(jīng)過三個階段,分別是

匹配玩家

選擇角色

加載數(shù)據(jù)

在這三個階段中,都需要互相等待對方完成才能繼續(xù)進(jìn)入下個階段。

這時可以采用CyclicBarrier來作為各個階段的節(jié)點,等待其他玩家到達(dá),在進(jìn)入下個階段。

定義繼承Runnable的類

這里名稱就叫做StartGame,包含兩個屬性

private String player;
private CyclicBarrier barrier;

通過構(gòu)造函數(shù)初始化兩個屬性

public StartGame(String player, CyclicBarrier barrier) {
 this.player = player;
 this.barrier = barrier;
}

run方法如下

public void run() {
 try {
  System.out.println(this.getPlayer()+" 開始匹配玩家...");
  findOtherPlayer();
  barrier.await();

  System.out.println(this.getPlayer()+" 進(jìn)行選擇角色...");
  choiceRole();
  System.out.println(this.getPlayer()+" 角色選擇完畢等待其他玩家...");
  barrier.await();

  System.out.println(this.getPlayer()+" 開始游戲,進(jìn)行游戲加載...");
  loading();
  System.out.println(this.getPlayer()+" 游戲加載完畢等待其他玩家加載完成...");
  barrier.await();


  start();
 } catch (Exception e){
  e.printStackTrace();
 }
}

其他的方法findOtherPlayer()、choiceRole()等待使用

Thread.sleep()

來模擬花費時間

編寫測試代碼

CyclicBarrier有兩個構(gòu)造函數(shù),如下

public CyclicBarrier(int parties) {}
public CyclicBarrier(int parties, Runnable barrierAction) {}

先來看看一個參數(shù)的構(gòu)造函數(shù)

CyclicBarrier(int parties)

public static void main(String[] args) throws IOException {
 CyclicBarrier barrier = new CyclicBarrier(5);

 Thread player1 = new Thread(new StartGame("1",barrier));
 Thread player2 = new Thread(new StartGame("2",barrier));
 Thread player3 = new Thread(new StartGame("3",barrier));
 Thread player4 = new Thread(new StartGame("4",barrier));
 Thread player5 = new Thread(new StartGame("5",barrier));

 player1.start();
 player2.start();
 player3.start();
 player4.start();
 player5.start();

 System.in.read();
}

測試結(jié)果如下

CyclicBarrier(int parties, Runnable barrierAction)

CyclicBarrier barrier = new CyclicBarrier(5);

替換為

CyclicBarrier barrier = new CyclicBarrier(5, () -> {
 try {
  System.out.println("階段完成,等待2秒...");
  Thread.sleep(2000);
  System.out.println("進(jìn)入下個階段...");
 } catch (InterruptedException e) {
  e.printStackTrace();
 }

});

再來看看效果

可以看到在到達(dá)某個節(jié)點時,會執(zhí)行實例化CyclicBarrier時傳入的Runnable對象。而且每一次到達(dá)都會執(zhí)行一次。

CyclicBarrier和CountDownLatch的區(qū)別

CountDownLatch CyclicBarrier
計數(shù)為0時,無法重置 計數(shù)達(dá)到0時,計數(shù)置為傳入的值重新開始
調(diào)用countDown()方法計數(shù)減一,調(diào)用await()方法只進(jìn)行阻塞,對計數(shù)沒任何影響 調(diào)用await()方法計數(shù)減一,若減一后的值不等于0,則線程阻塞
不可重復(fù)使用 可重復(fù)使用

await方法

public int await(){}
public int await(long timeout, TimeUnit unit){}

無參的await方法這里就不做介紹了,主要介紹下有參的await方法。

有參的await方法傳入兩個參數(shù),一個是時間、另一個是時間單位

當(dāng)調(diào)用有參的await方法時會出現(xiàn)下方兩個異常

java.util.concurrent.TimeoutException
java.util.concurrent.BrokenBarrierException

TimeoutException異常是指調(diào)用await方法后等待時間超過傳入的時間,此時會將CyclicBarrier的狀態(tài)變成broken,其他調(diào)用await方法將會拋出BrokenBarrierException異常,這時的CyclicBarrier將變得不可用,需要調(diào)用reset()方法重置CyclicBarrier的狀態(tài)。

為什么這么說?

源碼分析一波就可以看出來了

不管是有參還是無參的await方法都是調(diào)用CyclicBarrier的dowait(boolean timed, long nanos)方法,這個方法代碼太長了,截取部分貼出來

private int dowait(boolean timed, long nanos){
 //加鎖、try catch代碼
 final Generation g = generation;
 //判斷柵欄的狀態(tài)
 if (g.broken)
  throw new BrokenBarrierException();
 //...省略

 int index = --count;
 //(index == 0) 時的代碼,省略

 for (;;) {
  try {
   if (!timed)
    trip.await();
   else if (nanos > 0L)
    nanos = trip.awaitNanos(nanos);
  } catch (InterruptedException ie) {}

  //判斷柵欄的狀態(tài)
  if (g.broken)
   throw new BrokenBarrierException();

  if (g != generation)
   return index;
  //判斷是否是定時的,且已經(jīng)超時了
  if (timed && nanos <= 0L) {
   //打破柵欄的狀態(tài)
   breakBarrier();
   throw new TimeoutException();
  }
 }
 //解鎖
}

在代碼的尾部進(jìn)行判斷當(dāng)前等待是否已經(jīng)超時,如果是會調(diào)用breakBarrier()方法,且拋出TimeoutException異常,下面是breakBarrier()的代碼

private void breakBarrier() {
 generation.broken = true;
 count = parties;
 trip.signalAll();
}

代碼中將broken狀態(tài)置為true,表示當(dāng)前柵欄移除損壞狀態(tài),且重置柵欄數(shù)量,然后喚醒其他等待的線程。此時被喚醒的線程或者其他線程進(jìn)入dowait方法時,都會拋出BrokenBarrierException異常

案例源代碼地址:

https://github.com/rainbowda/learnWay/tree/master/learnConcurrency/src/main/java/com/learnConcurrency/utils/cyclicBarrier

相關(guān)文章

  • BeanUtils.copyProperties()屬性名相同但是類型不同問題

    BeanUtils.copyProperties()屬性名相同但是類型不同問題

    這篇文章主要介紹了BeanUtils.copyProperties()屬性名相同但是類型不同問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • Java簡單實現(xiàn)農(nóng)夫過河問題示例

    Java簡單實現(xiàn)農(nóng)夫過河問題示例

    這篇文章主要介紹了Java簡單實現(xiàn)農(nóng)夫過河問題,簡單描述了農(nóng)夫過河問題的概念、原理并結(jié)合簡單實例形式分析了java解決農(nóng)夫過河問題的相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • Mybatis返回單個實體或者返回List的實現(xiàn)

    Mybatis返回單個實體或者返回List的實現(xiàn)

    這篇文章主要介紹了Mybatis返回單個實體或者返回List的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • springCloud config本地配置操作

    springCloud config本地配置操作

    這篇文章主要介紹了springCloud config本地配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • SpringBoot2.x 參數(shù)校驗問題小結(jié)

    SpringBoot2.x 參數(shù)校驗問題小結(jié)

    這篇文章主要介紹了SpringBoot2.x 參數(shù)校驗一些問題總結(jié),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • SpringBoot3使用Jasypt實現(xiàn)配置文件信息加密的方法

    SpringBoot3使用Jasypt實現(xiàn)配置文件信息加密的方法

    對于一些單體項目而言,在沒有使用SpringCloud的情況下,配置文件中包含著大量的敏感信息,如果這些信息泄露出去將會對企業(yè)的資產(chǎn)產(chǎn)生重大威脅,因此,對配置文件中的敏感信息加密是一件極其必要的事,所以本文介紹了SpringBoot3使用Jasypt實現(xiàn)配置文件信息加密的方法
    2024-07-07
  • Java?Web實戰(zhàn)之使用三層架構(gòu)與Servlet構(gòu)建登錄注冊模塊

    Java?Web實戰(zhàn)之使用三層架構(gòu)與Servlet構(gòu)建登錄注冊模塊

    這篇文章介紹了如何使用三層架構(gòu)(View,?Service,?DAO)和JDBCTemplate技術(shù)在JavaWeb環(huán)境下實現(xiàn)登錄和注冊功能,詳細(xì)說明了構(gòu)建項目的步驟,包括創(chuàng)建數(shù)據(jù)庫表、實體類、DAO層、Service層、Servlet處理及頁面設(shè)計,需要的朋友可以參考下
    2024-10-10
  • break在scala和java中的區(qū)別解析

    break在scala和java中的區(qū)別解析

    這篇文章主要介紹了break在scala和java中的區(qū)別解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Log4j日志分類和過濾敏感字段的實例

    Log4j日志分類和過濾敏感字段的實例

    這篇文章主要介紹了Log4j日志分類和過濾敏感字段的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • MyBatis 動態(tài) SQL 優(yōu)化之標(biāo)簽的實戰(zhàn)與技巧(常見用法)

    MyBatis 動態(tài) SQL 優(yōu)化之標(biāo)簽的實戰(zhàn)與技巧(常見用法)

    本文通過詳細(xì)的示例和實際應(yīng)用場景,介紹了如何有效利用這些標(biāo)簽來優(yōu)化 MyBatis 配置,提升開發(fā)效率,確保 SQL 的高效執(zhí)行和安全性,感興趣的朋友跟隨小編一起看看吧
    2025-04-04

最新評論

育儿| 合肥市| 绥阳县| 武陟县| 宁武县| 犍为县| 互助| 安仁县| 兰州市| 威海市| 剑川县| 名山县| 华池县| 城市| 怀仁县| 天台县| 井冈山市| 浮梁县| 阳春市| 璧山县| 永寿县| 灵台县| 娱乐| 安西县| 沅陵县| 阳春市| 依兰县| 阿拉善右旗| 乌拉特后旗| 彭阳县| 玉龙| 措美县| 炉霍县| 临沂市| 延庆县| 清镇市| 山西省| 隆安县| 库车县| 郯城县| 石河子市|