Android Game Loop中的java.util.ConcurrentModificationException

时间:2016-11-17 17:31:15

标签: java android for-loop java.util.concurrent game-loop

我正在使用画布,在屏幕上移动对象,当对象到达画布的左侧(x = 0)时,同一类型的另一个对象被实例化,并开始在屏幕上移动。

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

在某个时刻,我在我的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 个答案:

答案 0 :(得分:1)

如果发生类似的事情,那么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)) {

...你将不再获得例外(但这仍然不会是#34;正确&#34;,如果你运行它,你会看到大量的空值被打印出来...... )

更好的是,将读取循环保持为......

for(String thing : things) {

...但是改变了列表的类型......

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