Java,你告诉我 fail-fast 是什么鬼?(2)

简介: Java,你告诉我 fail-fast 是什么鬼?

04、怎么避开 fail-fast 保护机制呢


通过上面的分析,相信大家都明白为什么不能在 for each 循环里进行元素的 remove 了。


那怎么避开 fail-fast 保护机制呢?毕竟删除元素是常规操作,咱不能因噎废食啊。


1)remove 后 break


List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("一个文章真特么有趣的程序员");
for (String str : list) {
  if ("沉默王二".equals(str)) {
  list.remove(str);
  break;
  }
}



我怎么这么聪明,忍不住骄傲一下。有读者不明白为什么吗?那我上面的源码分析可就白分析了,爬楼再看一遍吧!


略微透露一下原因:break 后循环就不再遍历了,意味着 Iterator 的 next 方法不再执行了,也就意味着 checkForComodification 方法不再执行了,所以异常也就不会抛出了。


但是呢,当 List 中有重复元素要删除的时候,break 就不合适了。


2)for 循环


List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("一个文章真特么有趣的程序员");
for (int i = 0, n = list.size(); i < n; i++) {
  String str = list.get(i);
  if ("沉默王二".equals(str)) {
  list.remove(str);
  }
}



for 循环虽然可以避开 fail-fast 保护机制,也就说 remove 元素后不再抛出异常;但是呢,这段程序在原则上是有问题的。为什么呢?


第一次循环的时候,i 为 0,list.size() 为 3,当执行完 remove 方法后,i 为 1,list.size() 却变成了 2,因为 list 的大小在 remove 后发生了变化,也就意味着“沉默王三”这个元素被跳过了。能明白吗?


remove 之前 list.get(1) 为“沉默王三”;但 remove 之后 list.get(1) 变成了“一个文章真特么有趣的程序员”,而 list.get(0) 变成了“沉默王三”。


3)Iterator


List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("一个文章真特么有趣的程序员");
Iterator<String> itr = list.iterator();
while (itr.hasNext()) {
  String str = itr.next();
  if ("沉默王二".equals(str)) {
  itr.remove();
  }
}



为什么使用 Iterator 的 remove 方法就可以避开 fail-fast 保护机制呢?看一下 remove 的源码就明白了。


public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();
    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}



虽然删除元素依然使用的是 ArrayList 的 remove 方法,但是删除完会执行 expectedModCount = modCount,保证了 expectedModCount 与 modCount 的同步。


05、最后


在 Java 中,fail-fast 从狭义上讲是针对多线程情况下的集合迭代器而言的。这一点可以从 ConcurrentModificationException 定义上看得出来。


This exception may be thrown by methods that have detected concurrent

modification of an object when such modification is not permissible.


For example, it is not generally permissible for one thread to modify a Collectionwhile another thread is iterating over it. In general, the results of theiteration are undefined under these circumstances. Some Iteratorimplementations (including those of all the general purpose collection implementationsprovided by the JRE) may choose to throw this exception if this behavior isdetected. Iterators that do this are known as fail-fast iterators,as they fail quickly and cleanly, rather that risking arbitrary,non-deterministic behavior at an undetermined time in the future.

再次拙劣地翻译一下。


该异常可能由于检测到对象在并发情况下被修改而抛出的,而这种修改是不允许的。


通常,这种操作是不允许的,比如说一个线程在修改集合,而另一个线程在迭代它。这种情况下,迭代的结果是不确定的。如果检测到这种行为,一些 Iterator(比如说 ArrayList 的内部类 Itr)就会选择抛出该异常。这样的迭代器被称为 fail-fast 迭代器,因为尽早的失败比未来出现不确定的风险更好。


既然是针对多线程,为什么我们之前的分析都是基于单线程的呢?因为从广义上讲,fail-fast 指的是当有异常或者错误发生时就立即中断执行的这种设计,从单线程的角度去分析,大家更容易明白。


你说对吗?


06、致谢


谢谢大家的阅读,原创不易,喜欢就随手点个赞👍,这将是我最强的写作动力。如果觉得文章对你有点帮助,还挺有趣,就关注一下我的公众号「沉默王二」;回复「666」更有 500G 高质量教学视频相送(已分门别类)。


相关文章
|
2月前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
60 5
|
安全 Java UED
深入刨析Java-ArrayList的Fail-Fast机制
本文将深入剖析Fail-Fast机制的原理,并结合代码示例演示如何正确处理并发修改问题,确保Java应用程序的稳定性和可靠性。
|
Java
【Java】从源码分析fail-fast和fail-safe是如何产生的
【Java】从源码分析fail-fast和fail-safe是如何产生的
81 0
|
Java API
Java 集合框架04-fail-fast总结
上一篇我们介绍了ArrayList的相关源码,这篇我们将了解一下fail-fast机制的相关知识
105 0
Java 集合框架04-fail-fast总结
|
安全 Java Android开发
java集合系列(4)fail-fast(面试常问)
今天来看java集合中一个常见的错误机制fail-fast机制。出现在这个错误机制的本质就是因为单线程和多线程的不同。下面就好好看一下这个机制是怎么是出现的。
156 0
java集合系列(4)fail-fast(面试常问)
Java fail-fast 机制
fail-fast 机制,即快速失败机制,是 Java 集合(Collection)中的一种错误检测机制,检测在迭代期间集合被修改的情况。fail-fast 机制并不保证在不同步的修改下一定会抛出异常,它只是尽最大努力去抛出,所以这种机制一般仅用于检测 bug。
Java fail-fast 机制
|
Java 程序员
Java,你告诉我 fail-fast 是什么鬼?
说起来真特么惭愧:十年 IT 老兵,Java 菜鸟一枚。今天我才了解到 Java 还有 fail-fast 一说。不得不感慨啊,学习真的是没有止境。只要肯学,就会有巨多巨多别人眼中的“旧”知识涌现出来,并且在我这全是新的。 能怎么办呢?除了羞愧,就只能赶紧全身心地投入学习,把这些知识掌握。
Java,你告诉我 fail-fast 是什么鬼?
|
Java
Java,你告诉我 fail-fast 是什么鬼?(1)
Java,你告诉我 fail-fast 是什么鬼?
93 0
Java,你告诉我 fail-fast 是什么鬼?(1)
|
安全 Java 应用服务中间件
深入理解Java中的fail-fast和fail-safe
什么是快速失败(fail-fast)和安全失败(fail-safe)?它们又和什么内容有关系。以上两点就是这篇文章的内容,废话不多话,正文请慢用。
1816 0
|
Java 索引
Java 集合系列04之 fail-fast总结(通过ArrayList来说明fail-fast的原理、解决办法)
概要 前面,我们已经学习了ArrayList。接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解。内容包括::1 fail-fast简介2 fail-fast示例3 fail-fast解决办法4 fail-fast原理5 解决fail-fast的原理 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3308762.html    1 fail-fast简介 fail-fast 机制是java集合(Collection)中的一种错误机制。
1409 0