2015-11-01 59 views
-1

我環顧四周,但找不到一個像樣的答案來解決我遇到的問題。我有一個不斷被修改和讀取的列表,但我不斷收到併發問題。注意:有2個線程不斷從這個列表中提取數據。 問題彈出doEntityTick()getEntity()。注意:doEntityTick問題是由我添加一個實體到列表引起的。嚴重併發問題

世界:

package UnNamedRpg.World; 

import java.awt.Rectangle; 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.Iterator; 

import UnNamedRpg.Player.Game.GameManager; 
import UnNamedRpg.World.Entity.Entity; 
import UnNamedRpg.World.Entity.EntityCharacter; 
import UnNamedRpg.World.Entity.EntityLiving; 
import UnNamedRpg.World.Entity.EntityProjectile; 


public class World { 

    private String name; 
    private ArrayList<Boundary> boundList = new ArrayList<Boundary>(); 
    private Collection<Entity> entityList = Collections.synchronizedList(new ArrayList<Entity>()); 

    public World(String name){ 
     setName(name); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public ArrayList<Entity> getEntityList(){ 
     ArrayList<Entity> newList = new ArrayList<Entity>(); 
     synchronized(entityList) { 
      Iterator<Entity> iter = entityList.iterator(); 
      while (iter.hasNext()) { 
       Entity ent = iter.next(); 
       newList.add(ent); 
      } 
     } 
     return newList; 
    } 

    public ArrayList<Entity> getEntityAtCoordinatePair(double x, double y){ 
     ArrayList<Entity> tempList = new ArrayList<Entity>(); 
     for(Entity ent : getEntityList()){ 
      Rectangle rect = new Rectangle((int)ent.getX(), (int)ent.getY(), ent.getWidth(), ent.getHeight()); 
      if(rect.contains(x, y)){ 
       tempList.add(ent); 
      } 
     } 
     return tempList; 
    } 

    public void addEntity(Entity ent){ 
     synchronized(entityList){ 
      entityList.add(ent); 
      if(ent.getID() == -1){ 
       ent.setID(entityList.size()); 
      } 
     } 
    } 

    public Entity getEntity(int id){ 
     synchronized(entityList) { 
       Iterator<Entity> i = entityList.iterator(); 
       while (i.hasNext()){ 
        Entity ent = i.next(); 
        if(ent.getID() == id){ 
         return ent; 
        } 
       } 

      } 
     return null; 
    } 

    public void doEntityTick(){ 
     synchronized(entityList) { 
      Iterator<Entity> iter = entityList.iterator(); 

      while (iter.hasNext()) { 
       Entity ent = iter.next(); 
       if(ent instanceof EntityLiving){ 
        EntityLiving entLiv = (EntityLiving)ent; 
        if(entLiv.getHealth() <= 0){ 
         entLiv.setDead(); 
        } 
        if(entLiv.isDead() && entLiv.getHealth() > 0){ 
         GameManager.isSpawning = true; 
        } 
        entLiv.doEntityTick(); 
       } 
       if(ent instanceof EntityProjectile){ 
        EntityProjectile entProj = (EntityProjectile)ent; 
        entProj.doTick(); 
        entProj.setCurrentRange(entProj.getCurrentRange() + 1); 
        if(entProj.getCurrentRange() >= entProj.getRange()){ 
         entProj.setDead(); 
        } 
       } 

       if(ent.isDead() && !(ent instanceof EntityCharacter)){ 
        iter.remove(); 
       } 
      } 
     } 
    } 

    public void addBounds(Boundary bounds){ 
     boundList.add(bounds); 
    } 

    public int getBoundsID(int x, int y){ 
     for(int i=0;i<boundList.size();i++){ 
      if(boundList.get(i).contains(x, y)) 
       return i; 
     } 
     return -1; 
    } 

    public int getBoundsID(Boundary bounds){ 
     for(int i=0;i<boundList.size();i++){ 
      if(boundList.get(i) == bounds) 
       return i; 
     } 
     return -1; 
    } 

    public void removeBounds(Boundary bounds){ 
     boundList.remove(bounds); 
    } 

    public Boundary getBounds(int x, int y){ 
     for(Boundary bounds : boundList){ 
      if(bounds.contains(x, y)){ 
       return bounds; 
      } 
     } 
     return null; 
    } 

    public boolean isInBounds(int posX, int posY){ 
     for(Boundary bounds : boundList){ 
      if(bounds.contains(posX, posY)){ 
       return true; 
      } 
     } 
     return false; 
    } 

} 

堆棧跟蹤:

Exception in thread "Thread-1" java.util.ConcurrentModificationException 
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
    at java.util.ArrayList$Itr.next(Unknown Source) 
    at UnNamedRpg.World.World.doEntityTick(World.java:83) 
    at UnNamedRpg.Player.Game.GameManager$1.run(GameManager.java:49) 
+3

你有什麼樣的併發問題? – Tsyvarev

+2

你爲什麼不在'getEntityList()'中迭代同步? – RealSkeptic

+0

@RealSkeptic改變了這一點,但問題仍然存在。 – Cyphereion

回答

0

所以看代碼一整天后,我設法找到一個解決。不是讓實體立即產卵,而是將它們粘在一個隊列中,等待下一個世界打勾以產生它們。我感謝所有試圖幫助我的人,並給了那些幫助我找到答案的+1。