激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java多線程開發之通過對戰游戲學習CyclicBarrier

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

2021-05-29 11:55云梟zd Java教程

這篇文章給大家分享了關于java多線程開發中通過對戰游戲學習CyclicBarrier的相關知識點內容,有興趣的朋友們學習參考下。

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

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

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

需求

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

解決方案

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

匹配玩家

選擇角色

加載數據

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

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

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

定義繼承runnable的類

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

?
1
2
private string player;
private cyclicbarrier barrier;

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

?
1
2
3
4
public startgame(string player, cyclicbarrier barrier) {
 this.player = player;
 this.barrier = barrier;
}

run方法如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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()等待使用

?
1
thread.sleep()

來模擬花費時間

編寫測試代碼

cyclicbarrier有兩個構造函數,如下

?
1
2
public cyclicbarrier(int parties) {}
public cyclicbarrier(int parties, runnable barrieraction) {}

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

cyclicbarrier(int parties)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);

替換為

?
1
2
3
4
5
6
7
8
9
10
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的區別

 

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

 

await方法

?
1
2
public int await(){}
public int await(long timeout, timeunit unit){}

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

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

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

?
1
2
java.util.concurrent.timeoutexception
java.util.concurrent.brokenbarrierexception

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

為什么這么說?

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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()的代碼

?
1
2
3
4
5
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

原文鏈接:https://www.cnblogs.com/fixzd/p/9562525.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产艳妇av视国产精选av一区 | 日日夜av | 亚洲自拍第一 | 免费观看又色又爽又黄的崩锅 | 中文字幕国| 久久96国产精品久久久 | 国产激爽大片在线播放 | 久久精品伊人网 | 成人三区四区 | 亚洲经典视频 | 特片网久久 | 久久777国产线看观看精品 | av中文字幕免费在线观看 | tube69xxxxxhd| 黄色av免费电影 | 久久国产成人午夜av浪潮 | 国产羞羞视频在线观看 | 欧美成人小视频 | 广州毛片 | 国产免费久久久久 | 亚洲精品a在线观看 | 国产精品成人一区二区三区电影毛片 | 久久久麻豆 | 日韩黄色片免费看 | 亚洲第一视频 | 久久17| 在线观看福利网站 | 毛片免费看的 | 精品一区二区三区四区在线 | 古装三级在线观看 | 亚洲综合精品成人 | 91美女福利视频 | 成熟女人特级毛片www免费 | 色综合久久久久久久久久 | 免费黄色在线电影 | 超级av在线| 亚洲小视频在线播放 | 免费毛片在线视频 | 在线中文字幕网站 | 91精品国产成人 | 国产毛片aaa一区二区三区视频 |