不清楚单独列表上的ConcurrentModificationException

时间:2016-02-02 11:03:22

标签: java concurrency

在课堂上我有这两种方法:

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? 我正在努力解决这个问题,任何线索都会受到欢迎。我尽量避免使用同步的惩罚。

问候

在代码中编辑了评论

2 个答案:

答案 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);