现在,我正在用Java试验一些基本的游戏概念。目前,它真正做的是显示两个框:一个是玩家可以用箭头键移动的,另一个是随机抖动的“敌人”。现在,我正在修复玩家在单击鼠标左键时向鼠标方向射击小方块的能力。按照现在的结构,我有四个类-一个包含“游戏”逻辑的JPanel,一个包含该面板的JFrame,一个Entity类,它只是一个物理对象的简单表示,具有位置、大小和速度以及移动它的方法,还有一个Projectile类,它使用一个特殊的移动方法来扩展Entity类,这个方法将它沿着给定给投射的构造函数的初始点和目标点计算出的路径移动一步。
我遇到的问题是试图更新投射物的位置。我有一个定时器在运行以更新非玩家控制的对象的位置,并且JPanel的actionPerformed()方法必须调用每个现有的射弹的move()方法。现在,当一个弹丸被创建时,我只是将它放入一个任意大小的弹丸阵列中,确保在阵列满的时候重新开始。actionPerformed()方法可以安全地与鼠标操作侦听器并发地作用于这个数组,但由于我在这方面的工作更多是为了学习,而不是为了解决一个简单的有效解决方案,所以我想知道是否有更好的方法来做到这一点,而不仅仅是拥有一个大小为999的数组。我一开始尝试使用ArrayList,但显然以并发访问错误告终。我尝试在数组中对投射物进行排队,然后将它们添加到actionPerformed()方法中的ArrayList中,但这给出了空指针错误。
(TLDR)所以我的问题是:是否有Java容器(set、map、queue等)支持并发访问?我不认为我需要一个顺序很重要的容器,因为我必须迭代容器中的每个元素,我只需要一个动态大小的容器,允许一个线程同时添加对象和另一个线程删除/调用对象。
发布于 2014-03-23 10:34:37
“我想知道有没有比仅仅使用一个大小为999的数组更好的方法。我一开始试过使用ArrayList,但显然以并发访问错误而告终。”
您可以使用ArrayList。您可能会得到一个ConcurrentModificationException,因为您可能会在循环访问某个对象时尝试从ArrayList中删除该对象。你可以看到一个类似的问题here。
解决方案是使用Iterator而不是循环来迭代对象。
来自Iterator API
然后,当您想要从ArrayList中删除对象时,可以使用Iterator.remove()方法。假设你有一个ArrayList中的Projectiles,你可以这样做
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。在for each循环中做不到的事情,因为你会得到ConcurrentModificationException。
你可以在The Collection Interface教程中看到更多如何使用迭代器的内容。您可以在this thread中阅读有关ConcurrentModificationException的更多信息
参见this answer,当在Timer中迭代List时,如果某个Asteroid不在屏幕上,则会通过iterator.remove()方法动态地将其从List中删除。

发布于 2014-03-24 01:13:30
如果您正在寻找并发安全容器,请尝试ConcurrentLinkedQueue或ConcurrentHashMap。
如果您后来发现需要对处理游戏中的实体的方式进行一些固有的排序,那么您可能想要使用PriorityQueue。
https://stackoverflow.com/questions/22585828
复制相似问题