Java:java.util.ConcurrentModificationException

时间:2012-02-24 19:53:32

标签: java arraylist

我正在制作2D,目前正在用子弹拍摄。子弹是一个单独的类。所有的子弹都存放在称为子弹的arraylist中。我试图让它在屏幕一侧(< -16)之外自我毁灭,但是当我尝试时它给了我这个错误。

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at GameCanvas.updateMovement(GameCanvas.java:94)
at GameCanvas.gameLoop(GameCanvas.java:63)
at GameCanvas.<init>(GameCanvas.java:28)
at GameClient.<init>(GameClient.java:68)
at GameClient.main(GameClient.java:29)

我认为它在销毁时会有所作为,我正在使用此代码来销毁它:

public void move() {

    if(x > -16) {
        x -= move_speed;
    } else {
        kill();
    }

}

public void kill() {
    ObjectHandler.bullets.remove(this);
}

updateMovement()方法:

public void updateMovement() {
    PlayerObject.update();

    for(Bullet bullet : ObjectHandler.bullets) {
        bullet.move();


    }

}

为什么这样做?感谢。

4 个答案:

答案 0 :(得分:4)

这是因为您在迭代时修改列表。

尝试“记住”kill所需的内容,并在通过整个列表后,浏览“内存”并执行相应的kill。这样,您将在迭代后修改列表。

E.g:

public void move() {

    if(x > -16) {
        x -= move_speed;
    } else {
        ObjectHandler.remember_to_kill(this);
    }

}

// in ObjectHandler:

private HashSet<type_of_object_to_kill> kill_memory = new...;

public void remember_to_kill() {
    this.kill_memory.add(this);
}

private void kill_from_memory() {
    for (type_of_object_to_kill obj: kill_memory) {
        ObjectHandler.bullets.remove(this);
    }
    ObjectHandler.kill_memory.clear();
}

// update movement:

public void updateMovement() {
    PlayerObject.update();

    for(Bullet bullet : ObjectHandler.bullets) {
        bullet.move();
    }
    ObjectHandler.kill_from_memory();
}

答案 1 :(得分:2)

从堆栈跟踪中,我们可以看到您有gameLoop()方法在updateMovement()中调用GameCanvas。后者在main线程中迭代子弹。同时,您的kill()方法会修改列表。这正是异常所说的,可以防止你受到进一步的伤害。

您必须同步bullets列表的访问权限或使用CopyOnWriteArrayList等线程安全集合。

答案 2 :(得分:0)

当您遍历列表并尝试同时从列表中删除/修改项时,通常会抛出此异常。我不确定到底发生了什么。更多代码示例会有所帮助。

答案 3 :(得分:0)

问题在于,当您同时阅读时,您正在尝试修改删除元素的集合。当然这可能很危险,所以抛出异常。如果您使用iterator,则可以利用其功能删除当前元素。

这样的事情:

public void updateMovement() {
    PlayerObject.update();

    Iterator<Bullet> iterator = ObjectHandler.bullets.iterator();
    while(iterator.hasNext()) {
        Bullet bullet = iterator.next();
        if(x > -16) {
            x -= move_speed;
        } else {
            iterator.remove();
        }
    }
}