黑马程序员技术交流社区

标题: 关于迭代器的问题 [打印本页]

作者: string1    时间: 2015-5-26 08:53
标题: 关于迭代器的问题
请问迭代器为什么会发生并发修改异常?

作者: zouzouzou    时间: 2015-5-26 08:53
你要知道迭代器的原理。首先,迭代器对象时通过iterator()方法获取的,因为每个单列集合都有自己的迭代器对象。迭代器对象是依据集合的存在而存在,如果在迭代过程中集合发生了变化,那么迭代器还没有发生变化,那么就会发生并发修改异常。
作者: zhuchangbao    时间: 2015-5-26 09:08
Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。  注意在遍历的过程中,只能对Map中的元素进行相应的处理,不能把Map元素增加或者把Map元素减少,也就是说,不能改变Map的size大小,就会出现异常(不能在遍历过程中修改删除或者增加map中的元素)  报出的异常为 java.util.ConcurrentModificationException 异常  public class ConcurrentModificationExceptionextends RuntimeException  当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
作者: 枕寒流    时间: 2015-5-26 09:39
list迭代的时候可以删除的,,怎么不会发生异常
作者: 人在旅途~东营    时间: 2015-5-26 15:45
并发修改异常发生的原因是在迭代中集合添加了元素,但没通知迭代器.
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
  所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性
作者: xxz    时间: 2015-5-27 06:37
并发修改异常发生的原因是在迭代中集合添加了元素,但没通知迭代器。
JDK文档描述是这样的:
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。

注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
作者: 黑马飞    时间: 2015-5-27 07:01
不用想那么多,只要一个数据可能被多个线程同时修改就有可能造成并发修改异常
作者: wwl0517    时间: 2015-5-27 08:06
学习一下,
作者: 曹乐乐    时间: 2015-5-27 18:54
在hashset和hashmap中保存了修改次数,迭代器会保存刚建立迭代器的时候的修改次数,每次添加删除都会增加修改次数,在迭代器调用next()的时候(调用next()方法会将next这个成员变量置为指向下一个元素或者为NULL),会比较迭代器和set或map的修改次数,若不相同,则会抛出异常,而hasnext不会比较这个次数。而hasnext这个方法不会比较次数,只是比较next这个成员变量是否为空。所以“打印“学习C#语言”后,迭代会结束。 但是在中间添加元素的话,因为下一个hashnext判断不为空,所以会执行next()这个方法,导致抛出异常。
作者: l598790586    时间: 2015-5-27 19:51
说的简单点:应该是map中使用迭代器获取元素时,如果你往里面存或者删除元素都会引起Iterator指向改变,这个时候next()方法就不知道是指向哪一个元素,而迭代器的remove只是移除最后一个元素,所以对迭代器的操作不会产生影响
作者: huadengaiyue    时间: 2015-5-28 11:50

学习一下,
作者: 山崩地裂    时间: 2015-5-30 10:21
学习一下。:)
作者: 少年闰土    时间: 2015-6-2 22:18
我的理解是,迭代器和集合操作是两个线程,而数据是共享的,所以他们同时操作时就有可能发生异常




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2