简体   繁体   English

奇怪的并发修改异常

[英]Weird Concurrent Modification Exception

For some reason I have looked at lots of posts and still I don't know how to fix this. 由于某种原因,我看了很多文章,但仍然不知道如何解决。 In the update method of my game, I have a for loop that updates all the existing GameObjects. 在我的游戏的更新方法中,我有一个for循环,用于更新所有现有的GameObject。

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

It says there is a ConcurrentModificationException error at the line of the for loop. 它说在for循环的行上有一个ConcurrentModificationException错误。 I have tried, like some people said, to get the iterator of the game object list and then use that, but it still doesn't work. 就像有人说的那样,我已经尝试过获取游戏对象列表的迭代器,然后使用它,但是它仍然无法正常工作。 Even though it says the error line is at the for loop, when I remove g.update there is no more error. 即使它说错误行在for循环中,当我删除g.update时也没有更多错误。 EDIT: I found the error. 编辑:我发现了错误。 It adds a game object to the list in the GameObjectManager.registerGameObject(). 它将游戏对象添加到GameObjectManager.registerGameObject()中的列表。 The only other class that uses the update is this: 使用该更新的唯一其他类是:

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);
        }
    }
}

The only update method is this: 唯一的更新方法是这样的:

@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));
    }
}

You can't modify a list while iterating it. 您无法在迭代时修改列表。 One of your game object's update methods must be adding or removing items. 游戏对象的更新方法之一必须是添加或删除项目。

You can iterate over a copy: 您可以遍历一个副本:

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

Or use a normal for loop, here objects can be added safely, but not removed: 或使用普通的for循环,可以安全地添加对象,但不能删除它们:

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

Or fix GameObjectManager.registerGameObject() to add to a temp list, not the main list and move them to the main list just before the existing code. 或修复GameObjectManager.registerGameObject()以将其添加到临时列表(而不是主列表)中,然后将其移动到现有代码之前的主列表中。 The same could be done for removals. 对于移除也可以这样做。

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

In this situation, this exception will be thrown when something is trying to modify an array whilst something else is currently using it (iterating over it etc). 在这种情况下,当某些对象试图修改数组而其他对象当前正在使用它时(在其上迭代等),将抛出此异常。 Like, a new monster is spawned on the map and added to some monster list, while the gameloop is currently iterating over said list. 例如,新的怪兽会在地图上生成并添加到某些怪兽列表中,而游戏循环目前正在该怪兽列表上进行迭代。 In your GameObjectManager class, what are you using to store the GameObject 's? 在您的GameObjectManager类中,您使用什么来存储GameObject If it's a normal list, you should consider changing it to CopyOnWriteArrayList or any other Thread-Safe list, it should fix the problem. 如果是正常列表,则应考虑将其更改为CopyOnWriteArrayList或任何其他线程安全列表,这应该可以解决该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM