Java中有两种类型的迭代器:故障安全和故障快速。
这意味着什么,它们之间的区别是什么?
答案 0 :(得分:79)
他们之间有什么区别......
“失败安全”意味着:它不会失败。严格地说,Java中的没有这样的东西作为故障安全迭代器。正确的术语是“弱一致”。 javadoc说:
“大多数并发Collection实现(包括大多数队列)也与通常的java.util约定不同,因为它们的迭代器和Spliterator提供弱一致而不是快速失败的遍历。”
通常,弱一致性意味着如果集合与迭代同时修改,则迭代所看到的保证较弱。 (详细信息将在每个并发集合类javadocs中指定。)
“快速失败”意味着:可能失败...并且积极检查失败条件,以便检测到失败条件(如果可能 1 ) 之前可以完成伤害。在Java中,通过抛出ConcurrentModificationException
来快速失败的迭代器失败。
“快速失败”和“弱一致”的替代方案是迭代失败不可预测的语义;例如有时给出错误的答案或抛出一个完全出乎意料的例外。 (这是早期Java版本中Enumeration
API的一些标准实现的行为。)
...它们与我们用于收集的迭代器不同。
没有。这些是标准Collection类型实现的迭代器的属性;即,它们要么“快速失败”,要么“弱一致”......当正确使用同步和Java内存模型 1 时。
使用集合对象上的volatile
计数器实现通常的失败快速迭代器。
Iterator
时,计数器的当前值嵌入Iterator
对象中。Iterator
操作时,该方法会比较两个计数器值,如果它们不同则会抛出CME。故障安全迭代器的实现通常很轻。它们通常依赖于特定列表实现的数据结构的属性。没有一般模式。 (阅读您感兴趣的特定集合类的源代码。)
1 - 骑手是快速失败行为假定应用程序在同步和内存模型方面正确。这意味着(例如)如果在没有正确同步的情况下迭代ArrayList
,最终结果可能是损坏的列表结果。 “快速失败”机制可能会检测到并发修改(虽然这不能保证),但它不会检测到底层的损坏。例如,Vector.iterator()
的{{3}}表示:
“迭代器的快速失败行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。快速失败的迭代器抛出
ConcurrentModificationException
因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应仅用于检测错误。“
答案 1 :(得分:37)
他们相当快速失败和弱一致类型:
来自java.util
包的迭代器抛出ConcurrentModificationException
如果在迭代时通过集合方法修改集合(添加/删除)
来自java.util.concurrent
包的迭代器通常迭代快照并允许并发修改,但在创建迭代器后可能无法反映集合更新。
答案 2 :(得分:22)
唯一的区别是故障安全迭代器不会抛出任何异常,与故障快速迭代器相反。
如果Collection在结构上被修改,而一个线程正在迭代它。这是因为它们可以克隆Collection而不是原始集合,因此它们被称为故障安全迭代器。
CopyOnWriteArrayList的迭代器是一个故障安全Iterator的示例,也是由ConcurrentHashMap编写的迭代器,keySet也是故障安全迭代器,永远不会在Java中抛出ConcurrentModificationException。
答案 3 :(得分:0)
这种情况与“并发处理”有关,意味着有更多的用户访问同一资源。在这种情况下,一个用户尝试修改导致“ ConcurrentProcessingException”的资源,因为在这种情况下,其他用户获取的数据不正确。这两种类型都与这种情况有关。
简单来说
失败/失败:
故障保护: