Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 主要并发问题_Java_List_Concurrency - Fatal编程技术网

Java 主要并发问题

Java 主要并发问题,java,list,concurrency,Java,List,Concurrency,我环顾四周,但我找不到一个像样的答案,我的问题。我有一个不断被修改和读取的列表,但我不断遇到并发问题。注意:有两个线程不断从该列表中提取数据。 问题会在doEntityTick()和getEntity()上弹出。注意:doEntityTick问题是由于我向列表中添加了一个实体引起的 世界: package UnNamedRpg.World; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Colle

我环顾四周,但我找不到一个像样的答案,我的问题。我有一个不断被修改和读取的列表,但我不断遇到并发问题。注意:有两个线程不断从该列表中提取数据。 问题会在
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;
    }

}

因此,在看了一整天的代码之后,我设法找到了一个修复方法。它不会让实体立即繁殖,而是将它们放入队列中,等待下一个世界的滴答声来繁殖它们。我感谢所有试图提供帮助的人,并向那些帮助我找到这个答案的a+1表示感谢。

您遇到了什么样的并发问题?为什么不在
getEntityList()
中围绕迭代进行同步?您说您有“问题”,但没有解释这些问题是什么。你只是有评论说“这里有问题”,“这里有问题”。什么问题?你有僵局吗?比赛条件?例外?糟糕的表现?正在发生什么,您希望发生什么?您确定这实际上是多线程的问题吗?当单个线程不一致地修改单个列表时,可能会出现此错误。从文档:请注意,此异常并不总是表示对象已被其他线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,该对象可能会引发此异常。例如,如果线程在使用fail-fast迭代器对集合进行迭代时直接修改集合,迭代器将抛出此异常。“与
ConcurrentModificationException
无关,但
World::addEntity()
的主体应通过在
entityList
上同步而成为原子体。”(或者列表大小可能是意外值),即使您的勾号值使其不太可能。
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)