Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
[Java]并发修改异常;迭代器不';行不通_Java - Fatal编程技术网

[Java]并发修改异常;迭代器不';行不通

[Java]并发修改异常;迭代器不';行不通,java,Java,在编写一个简单的游戏时,我遇到了一个并发修改异常,所以我看了这里,找到了两种不同的方法来修复它。它起作用了,但是,由于未知的原因,只有当玩家调用该函数时,AI玩家调用(相同)函数时才起作用 该函数的1.0版如下所示: public void eat(ArrayList<Enemy> enemys) { ArrayList<Enemy> toRemove = new ArrayList<Enemy>(); for(Enemy enemy : en

在编写一个简单的游戏时,我遇到了一个并发修改异常,所以我看了这里,找到了两种不同的方法来修复它。它起作用了,但是,由于未知的原因,只有当玩家调用该函数时,AI玩家调用(相同)函数时才起作用

该函数的1.0版如下所示:

public void eat(ArrayList<Enemy> enemys) {
    ArrayList<Enemy> toRemove = new ArrayList<Enemy>();
    for(Enemy enemy : enemys) {
        if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self
            if(collidesWith(enemy)) {
                if(width > enemy.width) {
                    width += enemy.width;
                    height = width;
                    toRemove.add(enemy);
                }
            }
        }
    }

    enemys.removeAll(toRemove);
}

堆栈跟踪将异常的位置放在方法
runGame()
Main.java
的第59行。这一行显然是循环的一部分,该循环对一个集合进行迭代,该集合不是通过控制
迭代器进行修改的。如果从该循环中注释掉对
eat()
的调用可以解决问题,那么传递给该方法的参数必须引用正在迭代的同一个集合。所以不要那样做

eat()
的第二个代码有更好的形式,但它没有解决这个问题,这与调用树上某个地方的迭代有关

您应该如何修复它取决于您想要的行为。特别是,如果您想避免被吃掉的敌人有机会吃掉其他敌人(正如您当前的代码所尝试的那样),那么您需要更复杂的东西。另一方面,如果你想让每一个敌人都有机会,即使它自己在游戏时钟的这个滴答声中被吃掉,那么你可以使用
敌人
集合的副本,可能是这样的:

public void runGame() {
    List<Enemy> enemysCopy = new ArrayList<>(enemys);

    for(Enemy enemy : enemys) {
        enemy.eat(enemysCopy);
    }
    enemys.retainAll(enemysCopy);
    player.eat(enemys);
    player.update();
}
public void runGame(){
List-enemysCopy=new-ArrayList(enemys);
为(敌人:敌人){
敌人。吃(敌人抄袭);
}
敌人保留(敌人副本);
玩家。吃(敌人);
player.update();
}
这就是问题所在:

for(Enemy enemy : enemys) {
    enemy.eat(enemys);
    enemy.update();
}
eat改变了你正在迭代的敌人。

一个可能的解决方案

public List eat(ArrayList<Enemy> enemys) {
    ArrayList<Enemy> toRemove = new ArrayList<Enemy>();
    for(Enemy enemy : enemys) {
        if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self
            if(collidesWith(enemy)) {
                if(width > enemy.width) {
                    width += enemy.width;
                    height = width;
                    toRemove.add(enemy);
                }
            }
        }
    }

    return toRemove;
}

public void runGame() {
    for(Enemy enemy : enemys) {
        List eaten = enemy.eat(enemys);
        enemy.update();
    }
    enemys.removeAll(eaten);
    player.eat(enemys);
    player.update();
}
公共列表eat(ArrayList敌人){
ArrayList toRemove=新建ArrayList();
为(敌人:敌人){
if(敌方.location.x!=location.x&&敌方.location.y!=location.y){//检查自身
如果(与(敌人)碰撞){
如果(宽度>敌人宽度){
宽度+=宽度;
高度=宽度;
移动。添加(敌人);
}
}
}
}
返乡搬迁;
}
public void runGame(){
为(敌人:敌人){
列表吃掉=敌人吃掉(敌人);
更新();
}
敌人移除(吃掉);
玩家。吃(敌人);
player.update();
}

您是否使用多个线程?@assylas当前,您如何将错误归因于方法
eat()
,但该方法没有出现在堆栈跟踪中?您的异常似乎出现在
runGame()
方法中。你能在这里发布吗?问题不在
eat()
方法本身,而是在围绕它的
for
循环中。由于
eat
更改了
敌人
列表,因此
for
循环使用的内部迭代器无效,从而导致异常。
public void runGame() {
    List<Enemy> enemysCopy = new ArrayList<>(enemys);

    for(Enemy enemy : enemys) {
        enemy.eat(enemysCopy);
    }
    enemys.retainAll(enemysCopy);
    player.eat(enemys);
    player.update();
}
for(Enemy enemy : enemys) {
    enemy.eat(enemys);
    enemy.update();
}
public List eat(ArrayList<Enemy> enemys) {
    ArrayList<Enemy> toRemove = new ArrayList<Enemy>();
    for(Enemy enemy : enemys) {
        if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self
            if(collidesWith(enemy)) {
                if(width > enemy.width) {
                    width += enemy.width;
                    height = width;
                    toRemove.add(enemy);
                }
            }
        }
    }

    return toRemove;
}

public void runGame() {
    for(Enemy enemy : enemys) {
        List eaten = enemy.eat(enemys);
        enemy.update();
    }
    enemys.removeAll(eaten);
    player.eat(enemys);
    player.update();
}