Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.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 单独列表上的ConcurrentModificationException不清楚_Java_Concurrency - Fatal编程技术网

Java 单独列表上的ConcurrentModificationException不清楚

Java 单独列表上的ConcurrentModificationException不清楚,java,concurrency,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 RoadOverl

在一个类中,我有两种方法:

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
             // ...
        }
}
public void notifyResult(列表结果){
ArrayList tempRoads=新的ArrayList();
用于(道路:结果){
//计算并存储覆盖
// ...
tempRoads.add(新道路覆盖层());
}
//更新完成时切换字段
这个位置=临时道路;
}
}
私人作废提款单(德国劳埃德船级社){
//在字段的当前实例上保留引用
//避免notifyResult中的并发修改
ArrayList PositionScope=this.positions;
int vertexCount=0;
对于(道路覆盖层道路:位置透视){//ConcurrentModificationException此处
// ...
}
}
这两个方法都在不同的线程中运行。在渲染内部,我没有对列表进行任何更改,据我所知,我在单独的列表上工作,那么这如何产生CME呢? 我正在努力解决这个问题,任何线索都欢迎。我尽量避免使用同步的惩罚

问候


在代码中编辑注释

通常最好制作列表的完整副本

ArrayList<RoadOverlay> positionsCopy = new ArrayList<Integer>(this.positions);
只有当列表的
elementData
在结构上被修改时,才能抛出
ConcurrentModificationException

结构修改是指改变列表大小的修改, 或者以某种方式干扰它,使迭代进行中 可能会产生错误的结果


问题是在drawRoadsVO方法中,您的var PositionScope实际上不是一个副本,而是对同一对象this.positions的引用

为了制作真实的副本,你应该

ArrayList<RoadOverlay> positionsCopy = new ArrayList(this.positions);
ArrayList positions=新的ArrayList(this.positions);

//复制以避免并发修改
您不复制列表。您只是有两个不同的引用指向同一个实例。我知道这不是一个浅拷贝,但它必须确保在同一个实例上保持遍历。你认为那没用?问题是,正如你所说,你的方法运行在不同的线程上。当您在同一实例上操作时,当您在
drawRoadsVO
中读取列表时,一个线程可能会修改该列表(这就是抛出CME的原因)。因此,在读取之前,您需要创建一个深度副本,或者使用线程安全的数据结构。好的,但是在第一种方法中,我在每次调用时创建一个新实例,所以我仍然需要同步?是的,我知道我应该更喜欢同步的深度副本,但此代码使用大量对象呈现OpenstreetMap中的道路层,我正在寻找每一个表演的热门。没有其他线程或方法修改集合。我将尝试将其设置为volatile,以防jvm在curtainHmm后面做奇怪的事情,现在我无法想象
volatile
如何解决这个问题。在
ArrayList.Itr
类CME的何处抛出?你能发布堆栈头跟踪吗?你是对的,它不会改变任何东西。这里有一个堆栈跟踪:
java.util.ConcurrentModificationException位于java.util.ArrayList$Itr.checkForComodification(未知源代码)位于java.util.ArrayList$Itr.next(未知源代码)位于org.mycompany.RoadProvider.drawRoadsVO[…],仍然需要Volatile来保证可见性
checkForComodification()
包含
if(modCount!=expectedModCount)抛出新的ConcurrentModificationException()所以结构修改发生在某个地方。对于调试,您可以在For循环之前创建
positionsCopy
的深度副本,然后使用
try{}catch(ConcurrentModificationException ex){//创建另一个
positionsCopy`的深度副本,并与第一个深度副本进行比较,或者使用java调试器在此处创建断点}`好的,我已经找到了问题所在。由于您提供了有关modcount的详细信息,我注意到modcount在渲染过程中发生了变化。这是notifiedResult中闭包的一个蹩脚位置,它在每次循环迭代中都会导致从局部到字段的切换。是的,很差劲。无论如何,谢谢你的帮助!当做
ArrayList<RoadOverlay> positionsCopy = new ArrayList(this.positions);