Java ArrayLists迭代器上ConcurrentModificationException的原因。next()

Java ArrayLists迭代器上ConcurrentModificationException的原因。next(),java,arraylist,concurrentmodification,Java,Arraylist,Concurrentmodification,我不知道当我迭代ArrayList时为什么会发生ConcurrentModificationException。ArrayList是methode作用域,因此执行相同代码的其他线程不应该看到它。至少如果我正确理解多线程和变量范围 Caused by: java.util.ConcurrentModificationException at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64) at com....

我不知道当我迭代ArrayList时为什么会发生ConcurrentModificationException。ArrayList是methode作用域,因此执行相同代码的其他线程不应该看到它。至少如果我正确理解多线程和变量范围

Caused by: java.util.ConcurrentModificationException
at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64)
at com....StrategyHandler.applyStrategy(StrategyHandler.java:184)

private List<Order> applyStrategy(StorageObjectTree storageObjectTree) {
    ...
    List<OrderHeader> finalList = new ArrayList<Order>();

    for (StorageObject storageObject : storageObjectTree.getStorageObjects()) {

        List<Order> currentOrders = strategy.process(storageObject);
        ...
        if (currentOrders != null) {
          Iterator<Order> iterator = currentOrders.iterator();
          while (iterator.hasNext()) {
            Order order = (Order) iterator.next();     // line 64
            // read some values from order
          }

          finalList.addAll(currentOrders);
        }
    }

    return finalList;
}
原因:java.util.ConcurrentModificationException
位于java.util.AbstractList$SimpleListIterator.next(AbstractList.java:64)
在com…StrategyHandler.applyStrategy(StrategyHandler.java:184)
私有列表应用程序策略(StorageObjectTree StorageObjectTree){
...
List finalList=new ArrayList();
对于(StorageObject-StorageObject:storageObjectTree.getStorageObjects()){
List currentOrders=strategy.process(storageObject);
...
if(currentOrders!=null){
迭代器迭代器=currentOrders.Iterator();
while(iterator.hasNext()){
Order Order=(Order)迭代器。next();//第64行
//按顺序读取一些值
}
finalList.addAll(当前订单);
}
}
回归终结者;
}

谁能告诉我问题的根源是什么吗?

如果您已经阅读了Java文档:

它清楚地说明了其发生的条件:

此异常可能由检测到并发的方法引发 当不允许修改对象时,对对象进行修改。 例如,通常不允许一个螺纹进行修改 当另一个线程在集合上迭代时,该集合将被删除。一般来说 在这些情况下,迭代的结果是未定义的。 一些迭代器实现(包括所有通用 JRE提供的目的集合实现可以选择 如果检测到此行为,则引发此异常。迭代器 这被称为fail fast迭代器,因为它们的失败速度很快,速度也很快 干净地说,更确切地说,是冒着任意的、不确定的行为的风险 未来不确定的时间

请注意,此异常并不总是表示对象具有 被另一个线程同时修改。如果是单线程 发出一系列违反 对象时,该对象可能会引发此异常。例如,如果 线程在集合上迭代时直接修改集合 集合,迭代器将抛出 例外

请注意,通常不能保证快速失效行为 说起来,在有人在场的情况下,不可能做出任何硬性保证 未同步的并发修改。快速失败操作抛出 ConcurrentModificationException尽最大努力。因此, 编写依赖此异常的程序是错误的 其正确性:ConcurrentModificationException仅应使用 检测错误

在您的情况下,正如您所说,您没有多个线程访问此列表。若从迭代器中读取的单个线程可能也在尝试向其写入,那个么根据上面第二段的内容,这仍然是可能的


希望这能有所帮助。

当您更改/添加/删除列表中的值时,以及在迭代列表的同时,出现了此异常。如果您同时使用多个线程

尝试通过
synchronized(currentOrders){/*您最后的代码*/}
来包围您的if。
我不确定这一点,但尝试一下。

取决于
策略的实现。过程(…)
可能是此实现仍然引用了它作为结果传回的列表。如果此实现中涉及多个线程,则可能是这些线程中的一个线程修改了列表,即使结果是该列表被传回。 (如果您知道“未来”模式,您可能会想象一个实现,其中一个方法立即返回一个空列表,然后使用另一个线程添加实际结果)


您可以尝试“围绕”结果列表创建一个新的ArrayList,并在复制的列表上进行迭代。

您可能需要阅读本文。如果看不到问题的来源,基本上可以切换并使用CopyOnWriteArrayList。

@NewBeee:虽然不需要强制转换,但这不是问题的原因。您没有添加或删除currentOrders的任何值,对吗?您需要在此处粘贴更多代码,您正在某个地方修改currentOrders。是否有其他线程正在访问strategy.process()方法返回的currentOrders列表?尝试在迭代之前复制到ArrayList中-这不是解决方案,但可能有助于找到问题
list currentOrders=new ArrayList(strategy.process(storageObject))