Android游戏循环中的java.util.ConcurrentModificationException

问题描述:

我使用画布,在屏幕上移动对象时,当一个对象碰到画布左侧(x = 0)时,同一类型的另一个对象被实例化,以及开始在屏幕上移动。Android游戏循环中的java.util.ConcurrentModificationException

一切工作正常,几个对象被创建并开始在屏幕上移动。

在某一点上,我收到一个并发修改例外在我的run方法在游戏循环是,其中gameObjs是一个ArrayList:

@Override 
public void run() { 

    while(isRunning){ 
     if(!myHolder.getSurface().isValid()) 
      continue; 
     Canvas canvas = myHolder.lockCanvas(); 
     canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite); 


     for(MyGameObject gameObj : gameObjs){ 
      gameObj.move(canvas); 
     } 

     myHolder.unlockCanvasAndPost(canvas); 
    } 

} 

我试图用一个Iterator,但仍然得到相同的错误。

我真的很感谢你的帮助。先谢谢你!如果这样的事情是发生在你的代码

+1

什么类型的对象是'gameObjs'? (即'ArrayList'?)另一个正在运行的线程是添加/删除此集合中的项目吗?如果发生这种情况并且允许,可以使用'CopyOnWriteArrayList'或其他允许并发修改的集合... – BretC

+0

对不起,我没有指定gameObjs是ArrayList – LDG

+0

_“我没有指定gameObjs是一个ArrayList“_但在问题中您具体说:_”...其中gameObjs是一个ArrayList“_。 –

Collections.synchronizedList(...)将无法正常工作。(抛出一个ConcurrentModificationException的...)

public class ConcurrentTest { 

    public static void main(String[] args) { 
     List<String> things = new ArrayList<>(); 

     Runnable modifyThread =() -> { 
      while(true) { 
       for(int k = 0; k < 1000; k++) { 
        things.add(String.valueOf(k)); 
       } 

       while(!things.isEmpty()) { 
        things.remove(0); 
       } 
      } 
     }; 

     Runnable readThread =() -> { 
      while(true) { 
       for(String thing : Collections.synchronizedList(things)) { 
        System.out.println(thing); 
       } 
      } 
     }; 

     new Thread(modifyThread).start(); 
     new Thread(readThread).start(); 
    } 
} 

试图找到其他地方,这列表正在修改中。当您迭代它时,必须有另一个线程操纵集合。

您可以在迭代之前获取列表的副本。

例如,在上面的代码,尝试...

for(String thing : new ArrayList<>(things)) { 

...而不是...

for(String thing : Collections.synchronizedList(things)) { 

...你将不再得到一个异常(但是这仍然不会是“正确的”,如果你运行它,你会看到被打印出来零点负荷......)

更妙的是,保持读取环路...

for(String thing : things) { 

...但改变列表类型...

List<String> things = new CopyOnWriteArrayList<>(); 
+0

谢谢@BretC我正在使用相同的循环,我刚刚修改列表** CopyOnWriteArrayList **,完美的作品! – LDG