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)