Java 从游戏中移除子弹时的ConcurrentModificationException

Java 从游戏中移除子弹时的ConcurrentModificationException,java,arraylist,concurrentmodification,Java,Arraylist,Concurrentmodification,我必须为我在大学的编程课程创建空间入侵者,这很好,但我在从游戏中移除子弹时遇到了问题 我把我所有的敌人和子弹都存储在不同的阵列列表中 这是我的主课 package uk.ac.wnc.pot13000765.space_invaders; import java.util.ArrayList; import org.lwjgl.LWJGLException; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMod

我必须为我在大学的编程课程创建空间入侵者,这很好,但我在从游戏中移除子弹时遇到了问题

我把我所有的敌人和子弹都存储在不同的阵列列表中

这是我的主课

package uk.ac.wnc.pot13000765.space_invaders;

import java.util.ArrayList;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class SpaceInvaders {

    private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
    private static ArrayList<Bullet> bullets = new ArrayList<Bullet>();
    private Player player;

    public SpaceInvaders() {

        //Setup and create the OpenGL Context + Window

        try {

            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.setTitle("Unit 14 Space Invaders in Java by Liam Potter - POT13000765");
            Display.create();

            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(0, 800, 0, 600, 1, -1);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);

            GL11.glClearColor(0f, 0f, 0f, 1f);
            GL11.glEnable(GL11.GL_BLEND);
            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        } catch(LWJGLException e) {
            System.err.print(e);
            System.exit(1);
        }

        Time.getDelta();
        Time.setLastFps(Time.getTime());

        //Setup
        player = new Player(40, 40, 50, 50);

        //Enemies
        enemies.add(new Enemy(40, 540, 25, 25));

        while(!Display.isCloseRequested()) {
            gameLoop(Time.getDelta());
        }

        Display.destroy();
    }

    private void gameLoop(int delta) {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        //Update
        player.update(delta);
        if(enemies.size() > 0) for(Enemy e: enemies) e.update(delta);
        if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);

        //Render
        player.draw();
        if(enemies.size() > 0) for(Enemy e: enemies) e.draw();
        if(bullets.size() > 0) for(Bullet b: bullets) b.draw();

        Display.sync(60);
        Display.update();
        Time.updateFps();
    }

    public int getWindowWidth() {
        return Display.getWidth();
    }

    public int getWindowHeight() {
        return Display.getHeight();
    }

    public static void spawnBullet(Bullet b) {
        bullets.add(b);
    }

    public static void destroyBullet(Bullet b) {
        bullets.remove(b);
    }

    public static void main(String[] args) {
        new SpaceInvaders();
    }
}
这正是我得到的错误:

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.gameLoop(SpaceInvaders.java:62)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.<init>(SpaceInvaders.java:50)
at uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.main(SpaceInvaders.java:91)
线程“main”java.util.ConcurrentModificationException中的异常 在java.util.ArrayList$Itr.checkForComodification处(未知源) 位于java.util.ArrayList$Itr.next(未知源) 在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.gameLoop(SpaceInvaders.java:62) 在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.(SpaceInvaders.java:50) 在uk.ac.wnc.pot13000765.space_invaders.SpaceInvaders.main(SpaceInvaders.java:91) 我知道我可以使用ListIterator来解决这个问题,但我不知道如何在我的主类中实现它们。

这个循环:

package uk.ac.wnc.pot13000765.space_invaders;

import java.util.ArrayList;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class SpaceInvaders {

    private ArrayList<Enemy> enemies = new ArrayList<Enemy>();
    private static ArrayList<Bullet> bullets = new ArrayList<Bullet>();
    private Player player;

    public SpaceInvaders() {

        //Setup and create the OpenGL Context + Window

        try {

            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.setTitle("Unit 14 Space Invaders in Java by Liam Potter - POT13000765");
            Display.create();

            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(0, 800, 0, 600, 1, -1);
            GL11.glMatrixMode(GL11.GL_MODELVIEW);

            GL11.glClearColor(0f, 0f, 0f, 1f);
            GL11.glEnable(GL11.GL_BLEND);
            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        } catch(LWJGLException e) {
            System.err.print(e);
            System.exit(1);
        }

        Time.getDelta();
        Time.setLastFps(Time.getTime());

        //Setup
        player = new Player(40, 40, 50, 50);

        //Enemies
        enemies.add(new Enemy(40, 540, 25, 25));

        while(!Display.isCloseRequested()) {
            gameLoop(Time.getDelta());
        }

        Display.destroy();
    }

    private void gameLoop(int delta) {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        //Update
        player.update(delta);
        if(enemies.size() > 0) for(Enemy e: enemies) e.update(delta);
        if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);

        //Render
        player.draw();
        if(enemies.size() > 0) for(Enemy e: enemies) e.draw();
        if(bullets.size() > 0) for(Bullet b: bullets) b.draw();

        Display.sync(60);
        Display.update();
        Time.updateFps();
    }

    public int getWindowWidth() {
        return Display.getWidth();
    }

    public int getWindowHeight() {
        return Display.getHeight();
    }

    public static void spawnBullet(Bullet b) {
        bullets.add(b);
    }

    public static void destroyBullet(Bullet b) {
        bullets.remove(b);
    }

    public static void main(String[] args) {
        new SpaceInvaders();
    }
}
    if(bullets.size() > 0) for(Bullet b: bullets) b.update(delta);
调用Bullet.update,它可以调用您正在执行的dispose()

    SpaceInvaders.destroyBullet(this);
它调用

    bullets.remove(b);

所以本质上,存在这样一种情况,即在ArrayList上循环,并在循环时从中删除对象。这是不允许的。您可以改为使用CopyOnWriteArrayList,该操作是允许的。不过,这相当昂贵,因为它在进行修改时会复制整个阵列。另一种可能的解决方案是在dispose()中收集要删除的项目符号,并在更新循环后将其删除。

发生这种情况的原因是您无法迭代ArrayList并同时修改元素。你能做的就是

(一)

Iteratorit=bullets.Iterator();
while(it.hasNext())
{
Bullet b=it.next();
项目符号。更新(b)
}

2) 此外(尽管我认为您应该做第一件事),您可以使用java.util.concurrent.CopyOnWriteArrayList,而不必更改代码。

谢谢,我现在正在使用CopyOnWriteArrayList。目前,它的资源密集程度并不重要,因为我最多只能在两台机器上运行它。
Iterator< Bullet > it = bullets.iterator();
while (it.hasNext() )
{
  Bullet b = it.next();
  bullets.update(b)  
}