Java 中有两种类型的迭代器:故障安全和快速故障。
这是什么意思,它们之间的区别是什么?
它们之间有什么区别...
“故障安全”(在工程中)是指某事以一种不会造成损害或造成损害最小的方式发生故障。严格来说, Java 中不存在故障安全迭代器。如果迭代器失败(在正常意义上的“失败”),您可以预期会发生损坏。
我怀疑您实际上是指“弱一致”迭代器。javadoc 说:
“大多数并发 Collection 实现(包括大多数队列)也不同于通常的 java.util 约定,因为它们的 Iterators 和 Spliterators 提供弱一致而不是快速失败遍历。”
通常,弱一致性意味着如果一个集合与迭代同时被修改,那么对迭代所看到的内容的保证会更弱。(详细信息将在每个并发集合类 javadocs 中指定。)
“Fail-fast”(在系统设计中)意味着积极检查故障条件,以便在造成过多损坏之前(在可能的情况下1 )检测到故障条件。在 Java 中,快速失败的迭代器通过抛出ConcurrentModificationException
.
“快速失败”和“弱一致”的替代方案是迭代失败不可预测的语义;例如,有时给出错误的答案或抛出意外的异常。Enumeration
(这是Java 早期版本中 API的一些标准实现的行为。)
...它们与我们用于收集的迭代器不同吗?
不,这些是标准 Collection 类型实现的迭代器的属性;即,它们要么是“快速失败”,要么是“弱一致”……当正确使用同步和Java 内存模型1时。
快速失败的迭代器通常使用volatile
集合对象上的计数器来实现。
Iterator
时,计数器的当前值嵌入到Iterator
对象中。Iterator
,该方法比较两个计数器值,如果它们不同,则抛出 CME。相比之下,弱一致性迭代器通常是轻量级的,并利用每个并发集合的内部数据结构的属性。没有通用模式。如果您有兴趣,请阅读不同集合类的源代码。
1 - 快速失败迭代器行为假设应用程序在同步和内存模型方面正确实现。(换句话说,应用程序是线程安全的。)例如,如果您在ArrayList
没有适当同步的情况下迭代一个,“快速失败”机制应该检测到并发修改(尽管不能保证),但可能不会阻止列表由于应用程序的不安全行为而损坏。为了说明,javadoc forVector.iterator()
是这样说的:
“无法保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。快速失败迭代器
ConcurrentModificationException
在尽力而为的基础上抛出。因此,它将是编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。”
它们是相当快速失败和弱一致性的类型:
如果集合在迭代时被集合的方法(添加/删除)修改,则java.util
包中的迭代器会抛出ConcurrentModificationException
包中的迭代器java.util.concurrent
通常迭代快照并允许并发修改,但在创建迭代器后可能不会反映集合更新。
唯一的区别是故障安全迭代器不会抛出任何异常,这与故障快速迭代器相反。
如果 Collection 在结构上被修改,而一个线程正在对其进行迭代。这是因为它们在 Collection 的克隆而不是原始集合上工作,这就是为什么它们被称为故障安全迭代器。
CopyOnWriteArrayList 的迭代器是故障安全迭代器的一个示例,也是由 ConcurrentHashMap 编写的迭代器 keySet 也是故障安全迭代器,在 Java 中从不抛出 ConcurrentModificationException。
这种情况与“并发处理”有关,意味着不止一个用户访问同一资源。在这种情况下,其中一个用户尝试修改导致“ConcurrentProcessingException”的资源,因为在这种情况下,其他用户会获得不正确的数据。这两种类型都与这种情况有关。
简单来说,
快速失败:
故障安全: