Ecplise,“线程中的异常”Thread-2“java.util.ConcurrentModificationException”

时间:2017-07-21 10:41:43

标签: java

我正在尝试制作一个小游戏,但我却陷入了这个错误。 我在互联网上搜索,我能找到的就是使用

List<Entity> entity = Collections.synchronizedList(new LinkedList<Entity>());

不幸的是,这并没有帮助我,我试图绕着for循环工作,但我仍然找不到修复。有人知道如何摆脱这个错误。

处理程序类

public List<Entity> entity = Collections.synchronizedList(new LinkedList<Entity>());
public List<Tile> tile = Collections.synchronizedList(new LinkedList<Tile>());

public void render(Graphics g){
    for(Entity entity : entity){
        entity.render(g);
    }
    for(Tile tile : tile){
        tile.render(g);
    }
}

public void update(){
    for(Entity entity : entity){
        entity.update();
    }

    for(Tile tile : tile){
        tile.update();
    }
}

public void addEntity(Entity entity){
    this.entity.add(entity);
}

public void removeEntity(Entity entity){
    this.entity.remove(entity);
}

public void addTile(Tile tile){
    this.tile.add(tile);
}

public void removeTile(Tile tile){
    this.tile.remove(tile);
}

抽象实体类(由每个实体扩展)

public int x,y,width,height;
public boolean solid;
public Id id;
public Handler handler;
public int velX,velY;
public boolean falling = true;
public boolean jumping = false;
public double gravity = 0.0;
public double health;
public boolean damageable = true;
public long damageTimer = System.currentTimeMillis();

public Entity(int x, int y, int width, int height, boolean solid, Id id,Handler handler){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.solid = solid;
    this.id = id;
    this.handler = handler;
    if(id==Id.Zombie) health=3.0;
    if(id==Id.Player) health=5.0;
}

public abstract void render(Graphics g);
public abstract void update();

public void die(){
    handler.removeEntity(this);
}

public int getX() {
    return x;
}

public void setX(int x) {
    this.x = x;
}

public int getY() {
    return y;
}

public void setY(int y) {
    this.y = y;
}

public boolean isSolid() {
    return solid;
}

public Id getId() {
    return id;
}

public int getVelX() {
    return velX;
}

public void setVelX(int velX) {
    this.velX = velX;
}

public int getVelY() {
    return velY;
}

public void setVelY(int velY) {
    this.velY = velY;
}

public Rectangle getBounds(){
    return new Rectangle(x,y,width,height);
}

public Rectangle getBoundsTop(){
    return new Rectangle(x,y-6,width,6);
}

public Rectangle getBoundsBottom(){
    return new Rectangle(x,y+height,width,6);
}

public Rectangle getBoundsLeft(){
    return new Rectangle(x-6,y,6,height);
}

public Rectangle getBoundsRight(){
    return new Rectangle(x+width,y,6,height);
}

public double getHealth() {
    return health;
}

public void setHealth(double health) {
    this.health = health;
}

错误:

Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:966)
at java.util.LinkedList$ListItr.next(LinkedList.java:888)
at Main.Handler.update(Handler.java:26)
at Main.GUI.update(GUI.java:100)
at Main.GUI.run(GUI.java:56)
at java.lang.Thread.run(Thread.java:745)

第26行是:

for(Entity entity : entity){

只有在有多个敌人的情况下被杀死时才会出现这个错误。 (特别是当有东西被杀死而另一个敌人真的非常非常接近时)

添加:Zombie类(Entity.update();应该为使用此类创建的每个对象执行此类update()方法)

public Zombie(int x, int y, int width, int height, boolean solid, Id id, Handler handler) {
    super(x, y, width, height, solid, id, handler);
}

@Override
public void render(Graphics g) {
    g.setColor(Color.RED);
    g.fillRect(x, y, width, height);
}

@Override
public void update() {
    x+=velX;
    y+=velY;

    if(x<=0) x=0;
    if(x+width >= GUI.WIDTH*GUI.SCALE+10) x = GUI.WIDTH*GUI.SCALE-width+10;
    if(y+height >= GUI.HEIGHT*GUI.SCALE+10) y = GUI.HEIGHT*GUI.SCALE-height+10;

    for(Tile tile: GUI.handler.tile){
        if(tile.getId()==Id.Stone){
            if(getBoundsTop().intersects(tile.getBounds())){
                y = tile.getY()+tile.height;
            }
            if(getBoundsBottom().intersects(tile.getBounds())){
                y = tile.getY()-height;
                gravity=0.0;
                falling=true;
                jumping=false;
            }
            if(getBoundsLeft().intersects(tile.getBounds())){
                x = tile.getX()+tile.width;
            }
            if(getBoundsRight().intersects(tile.getBounds())){
                x = tile.getX()-width;
            }
        }
    }
    for(Entity entity: GUI.handler.entity){
        if(entity.getId()==Id.Player){
            if(System.currentTimeMillis()-damageTimer>1000){
                damageable=true;
                entity.damageable = true;
                damageTimer+=1000;
            }
            if(new Rectangle(x-6,y-6,width+12,6).intersects(entity.getBounds())){
                entity.damageable = false;
                if(damageable){
                    if(entity.gravity>=0){
                        setHealth(getHealth()-1.0);
                        entity.falling = false;
                        entity.jumping = true;
                        entity.gravity = -10.0;
                        entity.setVelY((int) entity.gravity);
                    }
                    damageable=false;
                }
            }
            if(getBoundsBottom().intersects(entity.getBounds())){
                if(entity.damageable){
                    entity.setHealth(entity.getHealth()-1.0);
                    entity.damageable = false;
                }
            }
            if(getBoundsLeft().intersects(entity.getBounds())){
                if(entity.damageable){
                    entity.setHealth(entity.getHealth()-1.0);
                    entity.damageable = false;
                }
            }
            if(getBoundsRight().intersects(entity.getBounds())){
                if(entity.damageable){
                    entity.setHealth(entity.getHealth()-1.0);
                    entity.damageable = false;
                }
            }
        }
    }
    if(jumping){
        gravity+=0.2;
        setVelY((int)gravity);
        if(gravity>=0.5){
            gravity+=0.1;
        }
    }
    if(falling){
        gravity+=0.3;
        setVelY((int) gravity);
    }

    for(Entity entity : GUI.handler.entity){
        if(entity.getId()==Id.Player){
            if(entity.getY()<y&&!jumping&&getVelY()<=0){ 
                if(entity.getY()<y-10){
                    if(entity.getX()<x){ velX = -3; }else{ velX = 3; }
                    gravity = -10.0;
                    jumping = true;
                    falling = false;
                    velY = (int)gravity;
                } else {
                    if(entity.getX()<x){ velX = 3; }else{ velX = -3; }
                }
            }
        }
    }
    if(health<=0) die();
}

2 个答案:

答案 0 :(得分:1)

你的问题出在你的骰子方法中。您正在尝试编辑当前正在迭代的列表实体。这会导致你的错误。

不要修改其中的列表,而是尝试使用辅助列表来告诉您哪些实体已经死亡。在所有更新之后,您应该删除所有这些实体。

答案 1 :(得分:0)

ConcurrentModificationException表示在迭代时修改了集合。

Collections.synchronizedList无法保护您免受ConcurrentModificationException

的攻击

有两种解决方案。

  1. 您可以使用永远不会像CopyOnWriteArrayList那样抛出此异常的集合。但它只是隐藏问题。例如,如果你迭代实体集合,同时有人删除其中一个实体,你仍然会处理被移除的实体(这可能会造成像死僵尸一样的伤害仍然可以攻击)。
  2. 自己设计同步方案。它没有共同的模式,但您应该按照从不修改迭代的集合的方式设计代码。