- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章java多线程开发之通过对战游戏学习CyclicBarrier由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
cyclicbarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(cyclic)的屏障(barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,所有被屏障拦截的线程才会继续执行.
这篇文章将介绍cyclicbarrier这个同步工具类的以下几点 。
需求 。
继上一篇countdownlatch模拟游戏加载后,现在用户点击开始按钮后,需要匹配包括自己在内的五个玩家才能开始游戏,匹配玩家成功后进入到选择角色阶段。当5位玩家角色都选择完毕后,开始进入游戏。进入游戏时需要加载相关的数据,待全部玩家都加载完毕后正式开始游戏.
解决方案 。
从需求中可以知道,想要开始游戏需要经过三个阶段,分别是 。
匹配玩家 。
选择角色 。
加载数据 。
在这三个阶段中,都需要互相等待对方完成才能继续进入下个阶段.
这时可以采用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();
}
|
测试结果如下 。
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();
}
});
|
再来看看效果 。
可以看到在到达某个节点时,会执行实例化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 。
最后此篇关于java多线程开发之通过对战游戏学习CyclicBarrier的文章就讲到这里了,如果你想了解更多关于java多线程开发之通过对战游戏学习CyclicBarrier的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在关注 melon js tutorial .这是在我的 HUD.js 文件的顶部。 game.HUD = game.HUD || {} 我以前在其他例子中见过这个。 namespace.some
我刚刚制作了这个小游戏,用户可以点击。他可以看到他的点击,就像“cookieclicker”一样。 一切正常,除了一件事。 我尝试通过创建一个代码行变量来缩短我的代码,我重复了很多次。 documen
在此视频中:http://www.youtube.com/watch?v=BES9EKK4Aw4 Notch(我的世界的创造者)正在做他称之为“实时调试”的事情。他实际上是一边修改代码一边玩游戏,而不
两年前,我使用C#基于MonoGame编写了一款《俄罗斯方块》游戏,相关介绍可以参考【这篇文章】。最近,使用业余时间将之前的基于MonoGame的游戏开发框架重构了一下,于是,也就趁此机会将之前的《俄
1.题目 你和你的朋友,两个人一起玩 Nim 游戏: 桌子上有一堆石头。 你们轮流进行自己的回合, 你作为先手 。 每一回合,轮到的人拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。 假设
我正在创建平台游戏,有红色方 block (他们应该杀了我)和白色方 block (平台) 当我死时,我应该在当前级别的开始处复活。 我做了碰撞检测,但它只有在我移动时才有效(当我跳到红色方 bloc
因此,我正在处理(编程语言)中创建游戏突破,但无法弄清楚检查与 bat 碰撞的功能。 到目前为止,我写的关于与球棒碰撞的部分只是将球与底座碰撞并以相反的方向返回。目前,游戏是一种永无止境的现象,球只是
我试图让我的敌人射击我的玩家,但由于某种原因,子弹没有显示,也没有向玩家射击我什至不知道为什么,我什至在我的 window 上画了子弹 VIDEO bulls = [] runninggame = T
我正在尝试添加一个乒乓游戏框架。我希望每次球与 Racket 接触时球的大小都会增加。 这是我的尝试。第一 block 代码是我认为问题所在的地方。第二 block 是全类。 public class
我想知道 3D 游戏引擎编程通常需要什么样的数学?任何特定的数学(如向量几何)或计算算法(如快速傅立叶变换),或者这一切都被 DirectX/OpenGL 抽象掉了,所以不再需要高度复杂的数学? 最佳
我正在为自己的类(class)做一个霸气游戏,我一直在尝试通过添加许多void函数来做一些新的事情,但由于某种奇怪的原因,我的开发板无法正常工作,因为它说标识符“board”未定义,但是我有到目前为止
我在使用 mousePressed 和 mouseDragged 事件时遇到了一些问题。我正在尝试创建一款太空射击游戏,我希望玩家能够通过按下并移动鼠标来射击。我认为最大的问题是 mouseDragg
你好,我正在尝试基于概率实现战斗和准确性。这是我的代码,但效果不太好。 public String setAttackedPartOfBodyPercent(String probability) {
所以我必须实现纸牌游戏 war 。我一切都很顺利,除了当循环达到其中一张牌(数组列表)的大小时停止之外。我想要它做的是循环,直到其中一张牌是空的。并指导我如何做到这一点?我知道我的代码可以缩短,但我现
我正在做一个正交平铺 map Java 游戏,当我的船移动到 x 和 y 边界时,按方向键,它会停止移动(按预期),但如果我继续按该键,我的角色就会离开屏幕. 这是我正在使用的代码: @O
这里是 Ship、Asteroids、BaseShapeClass 类的完整代码。 Ship Class 的形状继承自 BaseShapeClass。 Asteroid类是主要的源代码,它声明了Gra
我正在开发这个随机数猜测游戏。在游戏结束时,我希望用户可以选择再次玩(或让其他人玩)。我发现了几个类似的线程和问题,但没有一个能够帮助我解决这个小问题。我很确定我可以以某种方式使用我的 while 循
我认为作为一个挑战,我应该编写一个基于 javascript 的游戏。我想要声音、图像和输入。模拟屏幕的背景(例如 640x480,其中包含我的所有图像)对于将页面的其余部分与“游戏”分开非常有用。我
我正在制作一个游戏,我将图标放在网格的节点中,并且我正在使用这个结构: typedef struct node{ int x,y; //coordinates for graphics.h
我正在研究我的游戏技能(主要是阵列)来生成敌人,现在子弹来击倒他们。我能够在测试时设置项目符号,但只有当我按下一个键(比方说空格键)并且中间没有间隔时才可见,所以浏览器无法一次接受那么多。 有没有什么
我是一名优秀的程序员,十分优秀!