通过将元素添加到位于另一个类的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)
我尝试包含一个迭代器,因为我在Google上搜索了如何解决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);
}
我认为某个地方可能存在初始化或声明错误,我只希望列表添加实体并解决该错误,因为我的render方法可以将ArrayList中的所有内容绘制到屏幕上。
答案 0 :(得分:2)
您的列表由多个线程使用,并且同时,如果一个线程尝试读取而另一个线程尝试写入,则将发生此异常,为避免这种情况,您可以使用CopyOnWriteArrayList list。 例: CopyOnWriteArrayList list = new CopyOnWriteArrayList <>();
使用此方法写入数据的成本更高,因此请阅读此api的所有优缺点。