-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)
你有什麼樣的併發問題? – Tsyvarev
你爲什麼不在'getEntityList()'中迭代同步? – RealSkeptic
@RealSkeptic改變了這一點,但問題仍然存在。 – Cyphereion