现在我正在尝试使用Java中的一些基本游戏概念。目前,所有它真正做的是显示两个框:一个玩家可以用箭头键移动,一个"敌人"那只是随意抖动。现在,只要他们点击鼠标左键,我就可以修复玩家在鼠标方向上拍摄小方块的能力。正如它现在的结构一样,我有四个类 - 一个持有"游戏的JPanel" logic,一个包含该面板的JFrame,一个Entity类,它只是一个具有位置,大小和速度的物理对象的简单表示,带有移动它的方法,还有一个Projectile类,它使用特殊的移动方法扩展Entity类它将沿着从给予弹丸构造函数的初始点和目标点计算出的路径向前移动一步。
我遇到的问题是试图更新射弹的位置。我有一个计时器运行来更新非玩家控制对象的位置,JPanel的actionPerformed()方法必须调用每个现有的弹丸的move()方法。现在,当一个抛射物被创建时,我只需将它放入任意大尺寸的弹丸阵列中,确保在阵列满时从[0]开始。 actionPerformed()方法可以安全地与鼠标动作监听器同时对这个数组起作用,但是因为我正在研究这个更多的学习而不是解决一个有效的简单解决方案,我想知道是否有&# 39;这是一个更好的方法,而不仅仅是一个大小为[999]的数组。我最初尝试使用ArrayList,但显然最终出现了并发访问错误。我尝试在一个数组中排队射弹,然后将它们添加到actionPerformed()方法中的ArrayList,但这给了我空指针错误。
(TLDR)所以我的问题:是否有任何Java容器(set,map,queue等)支持并发访问?我不认为我需要一个订单很重要的容器,因为我必须迭代容器中的每个元素,我只需要一个动态大小的容器,允许一个线程添加对象而另一个线程移除/调用对象同时。
答案 0 :(得分:0)
"我想知道是否有更好的方法来做这个,而不仅仅是拥有一个大小为[999]的数组。我最初尝试使用ArrayList,但显然最终出现了并发访问错误。"
您可以使用ArrayList
。您可能正在获得ConcurrentModificationException
,因为您可能正在尝试从ArrayList
中删除对象,同时循环播放该对象。您可以看到类似的问题here。
解决方案是使用Iterator
而不是循环来迭代对象。
来自Iterator API:
- 迭代器允许调用者在迭代期间使用明确定义的语义从底层集合中删除元素。
如果要从ArrayList
中删除对象,则可以使用Iterator.remove()
方法。所以说你Projectiles
中有ArrayList
,你可以这个
List<Projectile> projectiles = new ArrayList<>();
...
Iterator it = projectiles.iterator();
while (it.hasNext()) {
Projectile projectile = (Projectile)it.next();
if (projectile.hitEnemy()) {
it.remove();
}
}
it.remove()
删除迭代中的当前projectile
。对于每个循环都无法完成的事情,就像获得ConcurrentModificationException
一样。
您可以在The Collection Interface教程中查看更多如何使用迭代器。您可以在this thread
中详细了解ConcurrentModificationException
请参阅this answer其中,在List
中迭代Timer
时,如果Asteroid
不在屏幕上,则会从List
中移除iterator.remove()
动态地通过{{1}}方法。
答案 1 :(得分:0)
如果您正在寻找并发安全容器,请尝试ConcurrentLinkedQueue或ConcurrentHashMap。
如果您稍后发现在处理游戏中的实体时需要一些固有的顺序,则可能需要使用PriorityQueue。