0

我一直在努力寻找答案,但我不知道我做错了什么。我正在学习如何使用 JAVA 线程。事情是我正在做一个太空飞船游戏。我有一种创建敌人的方法(这些敌人被添加到一个 ArrayList 中,该 ArrayList 被绘制以产生运动效果,效果很好)。我有另一种方法可以在这个 ArrayList 中查找那些已经死去的敌人(dead 是一个布尔值,如果敌人从屏幕上消失或被杀死,它就会变成真的),如果他们(死了)它会从 ArrayList 中删除那些(不再画)。我有一个使用 createEnemy 方法的线程(它工作正常)。现在问题来了,我需要使用这个 ereaseEnemy 方法,但它给了我和并发错误,我尝试在这两种方法上使用同步,但 ereaseEnemy 方法永远不会开始工作。不知道如何解决这个问题。我应该停止第一个线程(创建者)以使其他线程工作吗?我在这里错过了什么吗?谢谢!

删除敌人的代码

for (Enemigo enemigo1 : enemigos) {
    if (!enemigo1.isEstaVivo()) { enemigos.remove(enemigo1); }
}
4

3 回答 3

6

你真的应该发布有问题的代码,但我可以做出一个有根据的猜测:你正在迭代ArrayList你正在调用的循环和内部list.remove(o)。抛出的异常是ConcurrentModificationException. List.remove()迭代时不允许调用任何方法;你必须使用Iterator.remove(). 这排除了在这个用例中使用增强的 for 循环。将您的代码更改为

for (Iterator<Enemigo> iter = enemigos.iterator(); iter.hasNext();)
  if (!iter.next().isEstaVivo()) iterator.remove();
于 2012-08-26T19:39:27.737 回答
1

两种可能的解决方案

1)在删除之前复制您的列表(如果大小太大,请注意性能问题)

ArrayList<enemigo> enemigosCopy= new ArrayList<enemigo>(); 
enemigosCopy.addAll(enemigos);
//Do your deleting thing on enemigosCopy

2) 使用迭代器

 Iterator i =enemigos.iterator();
 while (i.hasNext()) {
   enemigo o = i.next();
   if (!enemigo1.isEstaVivo()) {    
     i.remove(o);      
   }             
 }   
于 2012-08-26T19:49:06.207 回答
0

您不应该尝试自己同步线程。让 Java 通过使用这些java.util.concurrent类来为您做到这一点。在您的情况下,我会查看ConcurrentLinkedQueueorConcurrentMap以获得恒定的访问时间。您可以使用船舶 ID 作为地图的键。

您仍然需要控制dead在敌人上设置标志,以便多个线程正确处理它的访问。数据存储不会为您做到这一点,它只会确保所有线程的数据存储状态一致。

http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/package-summary.html

于 2012-08-26T19:37:53.293 回答