无法从其他类添加到对象 ArrayList



我因将元素添加到位于另一个类中的 ArrayList 而出现并发修改异常。 (GUI 程序)

Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891)
at sentinel/entity.EntityManager.tick(EntityManager.java:35)
at sentinel/worlds.World.tick(World.java:80)
at sentinel/state.GameState.tick(GameState.java:25)
at sentinel/game.Game.tick(Game.java:72)
at sentinel/game.Game.run(Game.java:115)
at java.base/java.lang.Thread.run(Thread.java:844)

我试图包含一个迭代器,因为我用谷歌搜索了如何解决ConcurrentModificationException。但是,它没有帮助,或者我用错了。

这是我将元素添加到 ArrayList 的类。

public class SentryHive extends StaticEntity{
private long lastSpawnTimer, spawnCooldown = 1000, spawnTimer = spawnCooldown;
private Random r = new Random();
public SentryHive(Handler handler, double x, double y) {
    super(handler, x, y, tiles.Tiles.TILEWIDTH*3, tiles.Tiles.TILEHEIGHT*3);
    bounds.x = 32*3;
    bounds.y = 64*4 - 80;
    bounds.width = 50;
    bounds.height = 32;
}
@Override
public void tick() {
    SpawnSentry();
}
public void SpawnSentry() {
    spawnCooldown = r.nextInt(100) * 1000;
    spawnTimer += System.currentTimeMillis() - lastSpawnTimer;
    lastSpawnTimer = System.currentTimeMillis();
    //Iterator<Entity> it = handler.getWorld().getEntityManager().getEntities().iterator();
    //while (it.hasNext()) {
        if(spawnTimer >= spawnCooldown) {  
            handler.getWorld().getEntityManager().addEntity(new Sentry(handler, 1080, 910, 10, 10));
        }
   // }
    spawnTimer = 0;
}

这是我程序的一部分,我在其中添加了其他实体(如果需要):

public class World {
private int width, height;
private int[][] tiles;
private int[][] entities;
private int spawnx, spawny;
private Handler handler;
private EntityManager entityManager;
private State state;
private ItemManager itemManager;
public int requiredSentry = 0;
private Random r = new Random();
//fun: ALT command R to change all of the same word in a file
public World(Handler handler, String path, String topper) {
    this.handler = handler;
    entityManager = new EntityManager(handler, new Player(handler, 600, 600));
    itemManager = new ItemManager(handler);
    entityManager.addEntity(new SentryHive(handler, 980, 810));
    loadWorld(path);
    for(int i = 0; i < width; i++) {
        for(int j = 0; j < height; j++) {
            int temp = r.nextInt(1000);
            if(temp >=1 && temp <= 10) {
                entityManager.addEntity(new DyingTree(handler, i*64, j*64));
            } else if(temp >= 11 && temp <= 15) {
                entityManager.addEntity(new Sentry(handler, i*64, j*64, 10, 10));
            } else if(temp >= 21 && temp <= 25) {
                entityManager.addEntity(new Beetle(handler, i*64, j*64, 40, 40));
            } else if(temp == 30) {
                entityManager.addEntity(new BeetleRed(handler, i*64, j*64, 40, 40));
            }
        }
    }
    entityManager.getPlayer().setX(spawnx * Tiles.TILEWIDTH);
    entityManager.getPlayer().setY(spawny * Tiles.TILEHEIGHT);
}

以下是我的实体管理器类(如果需要):

public class EntityManager {
private Handler handler;
private Player player;
private ArrayList<Entity> entities;
private Comparator<Entity> renderSorter = new Comparator<Entity>() {
    @Override
    public int compare(Entity a, Entity b) {
        if(a.getY() + a.getHeight() < b.getY() + b.getHeight()) 
            return -1;
        return 1;
    }
};
public EntityManager(Handler handler, Player player) {
    this.handler = handler;
    this.player = player;
    entities = new ArrayList<Entity>();
    addEntity(player);
}
public void tick() {
    Iterator<Entity> it = entities.iterator();
    while(it.hasNext()) {
        Entity e = it.next();
        e.tick();
        if(!e.isActive()) 
            it.remove();
    }
    entities.sort(renderSorter);
}
public void addEntity(Entity e) {
    entities.add(e);
}

我认为某处可能存在初始化或声明错误,我只想让列表添加实体并解决错误,因为我的渲染方法可以将 ArrayList 中的所有内容绘制到屏幕上。

您的列表被多个线程使用,同时如果一个线程尝试读取而另一个线程尝试写入,则会发生此异常,为避免这种情况,您可以使用CopyOnWriteArrayList列表。例:CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();

使用它写入数据的成本更高,因此请阅读此 API 的所有优缺点。

最新更新