主要并发问题

时间:2015-11-01 19:55:47

标签: java list concurrency

我环顾四周,但找不到我所遇到的问题的正确答案。我有一个不断修改和读取的列表,但我不断遇到并发问题。注意:有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)

1 个答案:

答案 0 :(得分:0)

所以经过一整天查看代码后,我设法找到了解决方法。它不是让实体立即产生,而是将它们粘在一个队列中并等待下一个世界滴答,以便产生它们。我感谢所有试图提供帮助的人,并给了那些帮助我找到答案的+1。