【问题标题】:Strange ConcurrentModificationException behavior [duplicate]奇怪的 ConcurrentModificationException 行为 [重复]
【发布时间】:2013-06-28 22:41:34
【问题描述】:

我不明白为什么这个方法会抛出异常:

public void add(Object obj){
    gameObjects.add(obj); //here the exception happens
}

...虽然这个没有:

public void add(Object obj){
    gameObjects.add(obj); // no exception actually happens here 
    gameObjects.remove(obj);
}

考虑到这是运行时异常,为什么会发生这种情况?

例外:

Exception in thread "Thread-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at threads.Main.tick(Main.java:181)
    at threads.Main.run(Main.java:104)

该方法为对象内的刻度方法调用。

gameObjects 不为空:

List<Object> gameObjects = new ArrayList<Object>(128);

【问题讨论】:

  • 信息不足。首先,有什么例外。另外,这些调用的上下文是什么?谁调用代码以及如何调用?
  • gameObjects是什么类型的?
  • gameObjects 是什么?是空的吗?
  • 在遍历列表时修改列表(通过添加或删除元素)时发生 ConcurrentModificationException。
  • 致所有反对者和密切投票者:如果他问为什么添加.remove() 调用会阻止抛出异常,那么这个问题实际上并没有那么糟糕。

标签: java concurrentmodification


【解决方案1】:

您不能在遍历时更改相同的object

JavaDoc说的

这个类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在任何结构上被修改 迭代器创建后的时间,除了通过 迭代器自己的删除或添加方法,迭代器会抛出一个 ConcurrentModificationException。

有关更多详细信息,请点击这些链接。它们可能会帮助您学习。

Concurrent Modification exception http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html

【讨论】:

    【解决方案2】:

    第一个方法抛出异常,因为您正在循环修改某个集合。第二个没有,因为集合没有净变化;你添加然后删除一个元素。

    请注意,检查ConcurrentModificationException 的不是add 方法;而是在每次循环迭代结束时检查集合是否有任何修改。

    【讨论】:

    • 但是Add 方法调用不可能知道下面的Remove 方法调用,所以它无法推理净变化并决定不引发异常。我错过了什么吗?
    • @TheodorosChatzigiannakis add 方法不是检查并发修改的方法。
    • 哦,是的,你是对的,我刚刚看到了堆栈跟踪。反正我很傻。
    【解决方案3】:

    根据doc

    检测到并发的方法可能会抛出此异常 在不允许修改时修改对象。

    例如一般不允许一个线程修改 一个集合,而另一个线程正在对其进行迭代。一般来说, 在这些情况下,迭代的结果是不确定的。 一些迭代器的实现(包括所有通用的 JRE 提供的目的集合实现)可以选择 如果检测到此行为,则抛出此异常。做的迭代器 这被称为快速失败迭代器,因为它们快速失败并且 干净利落,而不是冒着随意的、非确定性的行为的风险 未来的不确定时间。

    【讨论】:

      【解决方案4】:

      看起来您正在尝试将其添加到循环中。 Java 不允许这样做。如果您使用相同的方法添加然后删除,您实际上并没有做太多事情,净更改没有什么不同,因此您不会尝试在循环期间更改集合。

      如果你想添加它,你必须使用迭代器。

      【讨论】:

        猜你喜欢
        • 2015-07-26
        • 2020-04-26
        • 2015-08-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-26
        相关资源
        最近更新 更多