Fail-fast and Fail-safe in Java

2025年5月2日 | 阅读 4 分钟

Fail-fast 和 Fail-safe 是 Java 中的迭代器或集合。 Java SE 规范并不使用 Fail-safe 这个术语。我们使用 Fail-safe 来区分 非 Fail-fastFail-fast 迭代器。Fail-Fast 系统会尽快终止那些暴露了故障的操作,并停止整个操作。而 Fail-Safe 系统则不会终止那些暴露了故障的操作。Fail-safe 系统会尽量避免引发故障。

Fail-fast and Fail-safe in Java

Fail-fast 和 Fail-safe 是并发修改的概念。并发修改是指在另一个任务正在处理对象时,该对象被并发修改的过程。Fail-fast 和 Fail-safe 是用于迭代 Collection 对象的迭代器。

让我们逐一详细了解 Fail-fast 和 Fail-safe。

Fail-fast 迭代器

当我们使用 Fail-fast 迭代器时,如果在迭代集合的线程过程中向集合添加或删除了元素,它会立即抛出 ConcurrentModificationException。示例:HashMap 中的迭代器、ArrayList 上的迭代器等。

Fail-fast 迭代器使用 modCount,即一个内部标志,用于检查集合是否被结构性修改。当 Fail-fast 迭代器通过 next() 方法获取下一个值时,它会检查 modCount 标志的值。当迭代器发现 modCount 值被修改时,它就会抛出 ConcurrentModificationException。

让我们以 Fail-fast 迭代器为例,了解它在 Java 中是如何工作的。

FailFastIterator.java

输出

Fail-fast and Fail-safe in Java

让我们再看一个 Fail-fast 迭代器的例子,我们将对 ArrayList 使用迭代器。

FailFastIterator2.java

输出

Fail-fast and Fail-safe in Java

Fail-safe 迭代器

Java SE 规范不使用 Fail-safe 这个术语。最好称之为 非 Fail-fast 迭代器。Fail-safe 迭代器不会抛出 ConcurrentModificationException,它会尽量避免引发异常。Fail-safe 迭代器会创建原始集合或对象数组的副本,然后迭代这个复制的集合。在迭代器中进行的任何结构性修改都会影响复制的集合,而不是原始集合。因此,原始集合保持结构不变。

以下是与 Fail-safe 相关的一些要点:

  • 使用 Fail-safe 迭代器时,可以在线程迭代它的同时修改集合。
  • 当集合在迭代过程中被修改时,Fail-safe 迭代器不会抛出异常。
  • 为了遍历集合的元素,它会创建一个集合对象的副本。
  • 创建集合对象的副本需要额外的空间。例如:ConcurrentHashMap 上的迭代器、CopyOnWriteArrayList 上的迭代器等。

让我们以 Fail-safe 迭代器为例,了解它在 Java 中实际是如何工作的。

FailSafeIterator.java

输出

Fail-fast and Fail-safe in Java

让我们再看一个 Fail-safe 迭代器的例子,我们将对 CopyOnWriteArrayList 使用迭代器。

FailSafeIterator2.java

输出

Fail-fast and Fail-safe in Java

Fail-safe 和 Fail-fast 之间的区别

我们根据一些关键因素定义了 Fail-safe 和 Fail-fast 迭代器之间的主要区别。

序号。Fail-FastFail-Safe
1.Exception如果在线程迭代集合元素时添加、删除或更新这些元素,Fail-fast 会抛出并发修改异常。Fail-safe 迭代器会尝试避免引发故障,并且不会抛出异常。
2.性能和内存它在迭代时不需要更多内存,因为它迭代的是原始集合,并且所有修改都直接在原始集合上进行。它需要更多内存,因为需要处理复制的集合。所有修改都直接在复制的集合上进行,而不是在原始集合上。
3.修改迭代器在迭代时不能对集合进行更改。迭代器在迭代时可以对集合进行更改。
4.示例ArrayList 上的迭代器和 HashMap 上的迭代器。CopyOnWriteArrayList 上的迭代器和 ConcurrentHashMap 上的迭代器。