Java 中的fail safe和fail fast迭代器是什么

Java Collections 支持两种类型的迭代器:fail-safe(故障安全) 和 fail fast(快速失败)。快速失败迭代器和故障安全迭代器之间的主要区别在于底层集合在开始迭代时是否可以修改。如果您使用过像 ArrayList 这样的 Collection,那么您就会知道,当您迭代遍历它们时,其他线程不应修改该集合。如果迭代器在迭代开始后检测到任何结构更改,例如添加或删除新元素,则会抛出ConcurrentModificationException,这称为快速失败行为,这些迭代器称为快速失败迭代器,因为它们一旦检测到任何修改就会失败。

尽管当多个线程同时修改迭代器时,迭代器不一定会抛出此异常。即使在单线程中,当您使用 ArrayList 的 remove() 方法而不是 Iterator 的 remove() 方法来删​​除元素时,也可能会发生这种情况.

Java 1.4 中的大多数 Collection 类(例如Vector、ArrayList、HashMap、 HashSet )都具有fail-fast迭代器。另一种类型的迭代器是在 Java 1.5 中引入并发集合类时引入的。

这种迭代器使用原始集合的视图进行迭代,因此即使在迭代开始后修改了原始集合,也不会抛出 ConcurrentModificationException。

这意味着您可以迭代并使用过时的值,但这是您需要为fail-safe迭代器支付的成本.

Java 中fail-safe 迭代器和fail-fast迭代器的区别

为了更好地理解这两种迭代器之间的区别,本文中的案例使用 ArrayList 等传统集合和 CopyOnWriteArrayList 等并发集合的示例。尽管如此,让我们先逐一看看这两种迭代器的一些关键区别:

1)fail-fast迭代器在迭代过程中一旦检测到集合中的任何结构变化就会抛出ConcurrentModfiicationException ,这基本上改变了迭代器保存的 modCount 变量。 虽然快速失败迭代器不会抛出 CME。

  1. Fail-fast迭代器遍历原始集合类,而fail-safe迭代器遍历原始集合的副本或视图。这就是为什么他们没有检测到原始集合类的任何更改,这也意味着您可以使用陈旧的值进行操作。

  2. Java 1.4 集合类(如 ArrayList、HashSet 和 Vector)中的迭代器是快速失败的,而并发集合类(如 CopyOnWriteArrayList或CopyOnWriteArraySet返回的迭代器是失败安全的。

  3. 在 Java 中,同步集合返回的迭代器是快速失败的,而并发集合返回的迭代器是fail-safe的。

  4. Fail fast迭代器在实时数据中工作,但在数据修改时变得无效,而Fail fast迭代器始终保持一致。

何时使用快速失败和fail-safe迭代器

当你不担心集合在迭代过程中被修改时,请使用fail-safe 迭代器,因为fail-fast 迭代器不允许这样做。遗憾的是,你无法选择fail-safe 迭代器或fail-fast迭代器,这取决于你使用的是哪个集合类。

JDK 1.4 中的大多数集合(如 HashSet、Vector 和 ArrayList)都有fail-fast 迭代器,只有 JDK 1.5 中引入的并发集合(如 CopyOnWriteArrayList 和 CopyOnWriteArraySet)支持fail-safe迭代。

此外,如果要在迭代过程中删除元素,请使用迭代器的 remove() 方法,而不要使用 ArrayList 或 HashSet 等集合类提供的 remove 方法,因为这将导致 ConcurrentModificationException 异常。

总结

这就是 Java 中的 fail-safe迭代器和 fail-fast迭代器之间的区别。现在您知道,当通过添加或删除任何对象来修改基础集合类时,这只是两种行为不同的迭代器。

相关推荐
花花无缺1 分钟前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart1 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP2 小时前
MyBatis-mybatis入门与增删改查
java
孟陬6 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌6 小时前
一站式了解四种限流算法
java·后端·go
华仔啊6 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝7 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java
Nyarlathotep01137 小时前
SpringBoot Starter的用法以及原理
java·spring boot
wuwen58 小时前
WebFlux + Lettuce Reactive 中 SkyWalking 链路上下文丢失的修复实践
java