我不知道为什么迭代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;
}
有人能给我一个暗示可能是问题的根源吗?
答案 0 :(得分:2)
如果您已阅读ConcurrentModifcationException的Java文档:
它清楚地说明了它发生的条件:
检测到并发的方法可能抛出此异常 当不允许这种修改时修改对象。 例如,一个线程通常不允许修改 一个集合,而另一个线程正在迭代它。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器实现(包括所有通用的实现) 由JRE提供的目的集合实现可以选择 如果检测到此行为,则抛出此异常。那个迭代器 这被称为故障快速迭代器,因为它们很快就会失败 干净利落,而不是冒着任意的,非确定性的行为冒险 未来不确定的时间。
请注意,此异常并不总是表示对象具有 由另一个线程同时修改。如果是单线程 发出一系列违反合同的方法调用 一个对象,该对象可能抛出此异常。例如,如果是 线程在迭代时直接修改集合 使用失败快速迭代器进行集合,迭代器将抛出此异常 异常。
请注意,通常情况下无法保证快速失败的行为 说话,在场的情况下不可能做出任何硬性保证 不同步的并发修改。失败快速操作投掷 ConcurrentModificationException是尽力而为的。因此,它 编写一个依赖于此异常的程序是错误的 它的正确性:应该只使用ConcurrentModificationException 检测错误。
在您说的情况下,您没有多个线程访问此列表。如果你从迭代器读取的单个线程也可能试图写入它,那么它仍然可能如上所述。
希望这有帮助。
答案 1 :(得分:0)
当您更改/添加/删除列表中的值并在迭代它的同时发生此异常。如果你同时使用很多线程......
尝试通过synchronized(currentOrders) { /* YOUR LAST CODE */ }
包围你的if。
我不确定这个但是试一试。
答案 2 :(得分:0)
根据strategy.process(..)
的实现,可能是这个实现仍然引用了它作为结果传回的List。如果此实现中涉及多个线程,则即使在传回结果后,也可能由其中一个线程修改List。
(如果您知道&#34; Future&#34;模式,您可以想象一个实现,其中方法立即返回空List并稍后使用另一个Thread添加实际结果)
您可以尝试创建一个新的ArrayList&#34;&#34;结果列表并遍历此复制列表。
答案 3 :(得分:0)
您可能希望阅读this SO帖子。如果你看不到问题的来源,基本上就切换并使用CopyOnWriteArrayList。