奇怪的并发修改例外

时间:2014-11-02 19:53:24

标签: java jframe concurrentmodification

出于某种原因,我查看过很多帖子,但我仍然不知道如何解决这个问题。 在我的游戏的更新方法中,我有一个for循环来更新所有现有的GameObjects。

private static void update() {
    for (GameObject g : GameObjectManager.getGameObjects()) {
        g.update();
    }
    canvas.repaint();
}

它说for循环的行有一个ConcurrentModificationException错误。 像某些人说的那样,我试过要获取游戏对象列表的迭代器然后使用它,但它仍然无法正常工作。 即使它说错误行是在for循环,当我删除g.update时,没有更多的错误。 编辑:我发现了错误。它将游戏对象添加到GameObjectManager.registerGameObject()中的列表中。 使用此更新的唯一其他类是:

public class PaintCanvas extends JPanel {
    private static final long serialVersionUID = 6718161148154673832L;

    {
        this.setDoubleBuffered(true);
        this.setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        g.setColor(Color.RED);
        for (GameObject go : GameObjectManager.getGameObjects()) {
            g.fillRect(go.getPosition().getX(), go.getPosition().getY(), 30, 30);
        }
    }
}

唯一的更新方法是:

@Override
public void update() {
    Random r = new Random();
    int spawn = r.nextInt(100);
    // 5% Chance to spawn
    if (spawn <= 5) {
        Spawner s = new Spawner();
        s.setPosition(new Point(4, 50));
    }
}

2 个答案:

答案 0 :(得分:2)

迭代时无法修改列表。您的游戏对象的一个​​更新方法必须是添加或删除项目。

您可以迭代副本:

for (GameObject g : new ArrayList(GameObjectManager.getGameObjects())) {
    g.update();
}

或者使用普通for循环,这里的对象可以安全添加,但不能删除:

List<GameObject> objects = GameObjectManager.getGameObjects();
int size = objects.size();
for(int i = 0; i < size; i++) {
    GameObject g = objects.get(i);
    g.update();
}

或者修复GameObjectManager.registerGameObject()以添加到临时列表,而不是主列表,并将它们移到现有代码之前的主列表中。删除也可以这样做。

GameObjectManager.promoteNewGameObjects(); //promote objects added in the last frame
for (GameObject g : GameObjectManager.getGameObjects()) {
    g.update(); //as before
}

答案 1 :(得分:2)

在这种情况下,当某些东西试图修改数组而其他东西正在使用它时(迭代它等),将抛出此异常。就像,一个新怪物在地图上产生并添加到一些怪物列表中,而游戏循环当前正在迭代所述列表。在 GameObjectManager 类中,您使用什么来存储 GameObject ?如果它是普通列表,您应该考虑将其更改为CopyOnWriteArrayList或任何其他线程安全列表,它应该可以解决问题。