【问题标题】:How does an Iterator in Java know when to throw ConcurrentModification ExceptionJava 中的 Iterator 如何知道何时抛出 ConcurrentModification 异常
【发布时间】:2017-10-07 04:45:25
【问题描述】:

我有以下代码引发 ConcurrentModificationException,因为我在同一个列表上使用了两个不同的迭代器,其中一个正在修改列表。所以,第二个迭代器在读取列表时会抛出异常,因为其他迭代器已经修改了列表。

    List<Integer> list = new ArrayList<>();

    populate(list);//A method that adds integers to list

    ListIterator<Integer> iterator1 = list.listIterator();
    ListIterator<Integer> iterator2 = list.listIterator();

    while (iterator1.hasNext()) {
        if(iterator1.next() < 5)
            iterator1.remove();
    }

    while (iterator2.hasNext()){
        if(iterator2.next() < 5) {
         //Call handler   
        }
    }

我的问题是iterator2 如何在内部知道list 已被其他迭代器修改,如果它尚未到达iterator1 尚未删除的元素?它是如何发现其他一些iterator 已经改变了list?一种方法是跟踪大小,但这不是原因,因为其他迭代器可以替换任何元素。

【问题讨论】:

  • 你为什么在乎?您在修改列表之前创建了迭代器。可能有一个“脏”标志,但同样,您为什么要编写这样的代码来工作?
  • 我不希望这样的代码工作。但我确实很想知道这种情况是如何检测到的。
  • 使用免费提供的源代码!
  • 不知道这样的问题会受到处罚!会记住这一点。

标签: java exception collections concurrentmodification listiterator


【解决方案1】:

回答此类问题的一个好方法是查看源代码,例如the source code for ArrayList。搜索ConcurrentModificationException

你应该能够看出事情是这样工作的:

  • 集合对象有一个修改计数,该计数从零开始,并在发生添加或删除或类似操作时增加。
  • 创建迭代器对象时,我们将集合的当前修改计数存储在迭代器中。
  • 每次使用迭代器时,它都会检查集合的 mod 计数与迭代器在创建时获得的 mod 计数。如果这些值不同,则会引发异常。

在您的情况下,iterator1 对列表执行的删除操作会更改列表的结构操作计数 (modCount)。当iterator2 被要求删除时,它会看到它最初收到的expectedModCount,它与列表的当前mod 计数不同。

需要注意的是it.remove是一个特例。当迭代器自己删除时,它的expectedModCount 会相应地调整,以与底层列表保持同步。

【讨论】:

  • 得到了方法。谢谢!
  • 不客气。源代码在这里非常有用,变量和 cmets 的名称很酷。顺便说一句,我在答案中添加了更多内容——有人(正确地)投了反对票,我认为,因为我遗漏了关于迭代器本身执行删除操作的技术性。不改变基本思路,但是在这里完整就好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
  • 2011-09-20
  • 2021-09-03
  • 2015-04-26
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多