中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

java多線程開發之通過對戰游戲學習CyclicBarrier

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

創新互聯建站企業建站,10余年網站建設經驗,專注于網站建設技術,精于網頁設計,有多年建站和網站代運營經驗,設計師為客戶打造網絡企業風格,提供周到的建站售前咨詢和貼心的售后服務。對于網站設計、成都網站建設中不同領域進行深入了解和探索,創新互聯在網站建設中充分了解客戶行業的需求,以靈動的思維在網頁中充分展現,通過對客戶行業精準市場調研,為客戶提供的解決方案。

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

  1. 通過案例分析
  2. 兩種不同構造函數測試
  3. CyclicBarrier和CountDownLatch的區別
  4. await方法及源碼分析。

需求

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

解決方案

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

匹配玩家

選擇角色

加載數據

在這三個階段中,都需要互相等待對方完成才能繼續進入下個階段。

這時可以采用CyclicBarrier來作為各個階段的節點,等待其他玩家到達,在進入下個階段。

java多線程開發之通過對戰游戲學習CyclicBarrier

定義繼承Runnable的類

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

private String player;
private CyclicBarrier barrier;

通過構造函數初始化兩個屬性

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()+" 進行選擇角色...");
  choiceRole();
  System.out.println(this.getPlayer()+" 角色選擇完畢等待其他玩家...");
  barrier.await();

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


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

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

Thread.sleep()

來模擬花費時間

編寫測試代碼

CyclicBarrier有兩個構造函數,如下

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

先來看看一個參數的構造函數

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();
}

測試結果如下

java多線程開發之通過對戰游戲學習CyclicBarrier

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("進入下個階段...");
 } catch (InterruptedException e) {
  e.printStackTrace();
 }

});

再來看看效果

java多線程開發之通過對戰游戲學習CyclicBarrier

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

CyclicBarrier和CountDownLatch的區別

CountDownLatchCyclicBarrier
計數為0時,無法重置計數達到0時,計數置為傳入的值重新開始
調用countDown()方法計數減一,調用await()方法只進行阻塞,對計數沒任何影響調用await()方法計數減一,若減一后的值不等于0,則線程阻塞
不可重復使用可重復使用

await方法

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

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

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

當調用有參的await方法時會出現下方兩個異常

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

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

為什么這么說?

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

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

private int dowait(boolean timed, long nanos){
 //加鎖、try catch代碼
 final Generation g = generation;
 //判斷柵欄的狀態
 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) {}

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

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

在代碼的尾部進行判斷當前等待是否已經超時,如果是會調用breakBarrier()方法,且拋出TimeoutException異常,下面是breakBarrier()的代碼

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

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

案例源代碼地址:

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

當前題目:java多線程開發之通過對戰游戲學習CyclicBarrier
網站URL:http://m.2m8n56k.cn/article34/jdcese.html

成都網站建設公司_創新互聯,為您提供營銷型網站建設網站設計公司網站制作網站排名關鍵詞優化響應式網站

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

手機網站建設
主站蜘蛛池模板: 好妞操 | 日韩一级大片 | 欧美亚洲另类视频 | 人成午夜性刺激免费 | 欧美俄罗斯一级毛片激情 | 欧美性猛交xxx免费看人妖 | 欧美日本俄罗斯一级毛片 | 男人的天堂毛片 | 亚欧精品一区二区三区 | 国产日韩线路一线路二 | 6080伦理久久亚洲精品 | 亚洲欧美国产精品专区久久 | 亚洲一区2区三区4区5区 | 九九免费精品视频在这里 | 一级毛片私人影院老司机 | 精品欧美成人高清视频在线观看 | 免费成人在线网站 | 成人久久在线 | 中文乱码一二三四有限公司 | 99爱在线视频 | 免费成年人视频网站 | 国产片18在线观看 | 久久青草网站 | 亚洲免费视频一区二区三区 | 国产精品一区二区国产 | 红色记忆 | 中文精品爱久久久国产 | 国产成人免费午夜性视频 | 国产天堂亚洲精品 | 在线成人免费 | 香蕉午夜 | 欧美国产精品不卡在线观看 | 最新中文字幕一区二区乱码 | 国产三级久久 | 直接看的毛片 | 欧美成人做爰网站 | 波多结衣一区二区三区 | 国产深夜福利在线观看网站 | 午夜神马理论 | 久久久免费网站 | 精品国产一区二区三区不卡 |