在课堂上我有这两种方法:
public void notifyResult(List<Road> result) {
ArrayList<RoadOverlay> tempRoads = new ArrayList<>();
for(Road road:result){
// Computes and stores the overlays
// ...
tempRoads.add(new RoadOverlay());
}
//switch field when update is done
this.positions = tempRoads;
}
}
private void drawRoadsVO(GL gl) {
// keep a reference on the current instance of the field
// to avoid concurrent modification in notifyResult
ArrayList<RoadOverlay> positionsCopy = this.positions;
int vertexCount = 0;
for (RoadOverlay road : positionsCopy) { //ConcurrentModificationException here
// ...
}
}
两种方法都在不同的线程中运行。内部渲染我没有对列表进行任何更改,据我所知,我在单独的列表上工作,那么这怎么能产生CME? 我正在努力解决这个问题,任何线索都会受到欢迎。我尽量避免使用同步的惩罚。
问候
在代码中编辑了评论
答案 0 :(得分:1)
制作列表的完整副本通常更好
ArrayList<RoadOverlay> positionsCopy = new ArrayList<Integer>(this.positions);
对于ConcurrentModificationException
,您的代码看起来很好,可能是您正在修改其他类方法中的当前this.positions
?
请注意,您的this.positions
变量应声明为volatile
。
这是ArrayList迭代器的next()
方法
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
ConcurrentModificationException
只有在列表&{39} elementData
结构修改的情况下才会被抛出
结构修改是那些改变列表大小的修改, 或以其他方式扰乱它,以便进行迭代 可能会产生不正确的结果。
答案 1 :(得分:1)
问题出在drawRoadsVO方法中你的var positionsCopy实际上不是一个副本,而是对同一个对象this.positions的引用。
为了进行实际复制,你应该做
ArrayList<RoadOverlay> positionsCopy = new ArrayList(this.positions);