2017-07-21 18 views
0

小さなゲームを作ろうとしていますが、このエラーが発生しました。 私は、インターネット上で検索し、私は見つけることができるすべては、残念ながら、これは私を助けていない 「スレッドの例外」Thread-2「java.util.ConcurrentModificationException」

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

を使用していたと私は、forループのまわりで私のように動作するようにしようとしたが、私はまだ修正を見つけることができませんでした。誰かがこのバグをどのように取り除くことができるか知っていますか?

Handlerクラス

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); 
} 

抽象Entityクラス(すべてのエンティティによって拡張されます)

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){ 

複数の敵がいるときに何かが殺されたときだけ、バグが発生します。

が追加されました:ゾンビクラス(このクラスで作成された各オブジェクトに対してこのクラスの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(); 
} 
+0

'entity.update()'には何がありますか? 'Entity'では、このメソッドは抽象メソッドです。私は実装の1つが 'エンティティ'コレクションを変更すると思います。 – talex

+0

質問の内容に自分の質問の回答を追加しました。 –

+0

@NoahSnoeksあなたの問題はあなたの死の方法です。現在反復されているリストのエンティティを編集しようとしています。それはあなたのエラーの原因となります。 – Shirkam

答えて

1

あなたの問題はあなたのダイメソッドにあります。現在反復されているリストエンティティを編集しようとしています。それはあなたのエラーの原因となります。

その中のリストを変更する代わりに、どのエンティティが死亡したかを示す補足リストを用意してください。すべての更新後、これらのエンティティをすべて削除する必要があります。

+0

ありがとう、これは動作します! –

+0

それがうまくいくなら、みんなが見ることができるようにこの回答を受け入れてください。 – Shirkam

0

ConcurrentModificationExceptionは、反復処理中にコレクションが変更されたことを意味します。

Collections.synchronizedListは、ConcurrentModificationExceptionからあなたを保護しません。

2つの解決策があります。

  1. CopyOnWriteArrayListのようにこの例外を発生させないコレクションを使用できます。しかし、問題を隠すだけです。たとえば、エンティティのコレクションを繰り返し処理すると同時に、削除されたエンティティを処理すると同時に、削除されたエンティティを処理します(死んだゾンビのような害を引き起こす可能性があります)。
  2. 自分で設計を同期する。共通のパターンはありませんが、反復するコレクションを決して変更しないようにコードを設計する必要があります。
関連する問題