fail-safe fail-fast知多少
fail-safe fail-fast知多少
简介
我们在使用集合类的时候,通常会需要去遍历集合中的元素,并在遍历中对其中的元素进行处理。这时候我们就要用到Iterator,经常写程序的朋友应该都知道,在Iterator遍历的过程中,是不能够修改集合数据的,否则就会抛出ConcurrentModificationException。
因为ConcurrentModificationException的存在,就把Iterator分成了两类,Fail-fast和Fail-safe。
Fail-fast Iterator
Fail-fast看名字就知道它的意思是失败的非常快。就是说如果在遍历的过程中修改了集合的结构,则就会立刻报错。
Fail-fast通常在下面两种情况下抛出ConcurrentModificationException:
- 单线程的环境中
如果在单线程的环境中,iterator创建之后,如果不是通过iterator自身的remove方法,而是通过调用其他的方法修改了集合的结构,则会报错。
- 多线程的环境中
如果一个线程中创建了iterator,而在另外一个线程中修改了集合的结构,则会报错。
我们先看一个Fail-fast的例子:
Map<Integer,String> users = new HashMap<>();
users.put(1, "jack");
users.put(2, "alice");
users.put(3, "jone");
Iterator iterator1 = users.keySet().iterator();
//not modify key, so no exception
while (iterator1.hasNext())
{
log.info("{}",users.get(iterator1.next()));
users.put(2, "mark");
}
上面的例子中,我们构建了一个Map,然后遍历该map的key,在遍历过程中,我们修改了map的value。
运行发现,程序完美执行,并没有报任何异常。
这是因为我们遍历的是map的key,只要map的key没有被手动修改,就没有问题。
再看一个例子:
Map<Integer,String> users = new HashMap<>();
users.put(1, "jack");
users.put(2, "alice");
users.put(3, "jone");
Iterator iterator1 = users.keySet().iterator();
Iterator iterator2 = users.keySet().iterator();
//modify key,get exception
while (iterator2.hasNext())
{
log.info("{}",users.get(iterator2.next()));
users.put(4, "mark");
}
上面的例子中,我们在遍历map的key的同时,对key进行了修改。这种情况下就会报错。
Fail-fast 的原理
为什么修改了集合的结构就会报异常呢?
我们以ArrayList为例,来讲解下Fail-fast 的原理。
在AbstractList中,定义了一个modCount变量:
protected transient int modCount = 0;
在遍历的过程中都会去调用checkForComodification()方法来对modCount进行检测:
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
如果检测的结果不是所预期的,就会报错:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
在创建Iterator的时候会复制当前的modCount进行比较,而这个modCount在每次集合修改的时候都会进行变动,最终导致Iterator中的modCount和现有的modCount是不一致的。
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
注意,Fail-fast并不保证所有的修改都会报错,我们不能够依赖ConcurrentModificationException来判断遍历中集合是否被修改。
Fail-safe Iterator
我们再来讲一下Fail-safe,Fail-safe的意思是在遍历的过程中,如果对集合进行修改是不会报错的。
Concurrent包下面的类型都是Fail-safe的。看一个ConcurrentHashMap的例子:
Map<Integer,String> users = new ConcurrentHashMap<>();
users.put(1, "jack");
users.put(2, "alice");
users.put(3, "jone");
Iterator iterator1 = users.keySet().iterator();
//not modify key, so no exception
while (iterator1.hasNext())
{
log.info("{}",users.get(iterator1.next()));
users.put(2, "mark");
}
Iterator iterator2 = users.keySet().iterator();
//modify key,get exception
while (iterator2.hasNext())
{
log.info("{}",users.get(iterator2.next()));
users.put(4, "mark");
}
上面的例子完美执行,不会报错。
总结
Fail-fast 和 Fail-safe 是集合遍历的重要概念,希望大家能够掌握。
本文的例子https://github.com/ddean2009/learn-java-streams
欢迎关注我的公众号:程序那些事,更多精彩等着您!
更多内容请访问 www.flydean.com
fail-safe fail-fast知多少的更多相关文章
- Fail Fast and Fail Safe Iterators in Java
https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/ Fail Fast and Fail Safe Iterators ...
- fail fast和fail safe策略
优先考虑出现异常的场景,当程序出现异常的时候,直接抛出异常,随后程序终止 import java.util.ArrayList; import java.util.Collections; impor ...
- 快速失败(fail—fast)和 安全失败(fail—safe)
快速失败(fail-fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的结构进行了修改(增加.删除),则会抛出Concurrent Modification Exception. 原理 ...
- [Oracle]Oracle Fail Safe 与 SQLNET.AUTHENTICATION_SERVICES关系
现象: 在使用 OFS (Oracle Fail Safe)的环境中,把数据库的 SQLNET.AUTHENTICATION_SERVICES 从 NTS 改为 NONE之后,当从 Oracle Fa ...
- Java集合框架中的快速失败(fail—fast)机制
fail-fast机制,即快速失败机制,是java集合框架中的一种错误检测机制.多线程下用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除),则会抛出Concurre ...
- 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组
E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
- 【bzoj2434-阿狸的打字机】AC自动机+fail树+优化
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23083 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一 ...
- CF 163E. e-Government ac自动机+fail树+树状数组
E. e-Government 题目: 给出n个字符串,表示n个人名,有两种操作: ?string ,统计字符串string中出现的属于城市居民的次数. +id,把编号为id的人变为城市居民,如果已经 ...
- AC自动机相关Fail树和Trie图相关基础知识
装载自55242字符串AC自动机专栏 fail树 定义 把所有fail指针逆向,这样就得到了一棵树 (因为每个节点的出度都为1,所以逆向后每个节点入度为1,所以得到的是一棵树) 还账- 有了这个东西, ...
随机推荐
- Modbus协议和应用开发介绍
因业务需要了解Modbus协议的使用,因此对Modbus的协议,以及相应的C#处理应用进行了解,针对协议的几种方式(RTU.ASCII.TCPIP)进行了封装,以及对Modbus的各种功能码的特点进行 ...
- WDK驱动开发点滴
老程序员做新方向,老树发新芽,作为菜鸟的我,写点心得,用以记录并与同行交流 1对一些概念的理解: KMDF与UMDF.两者的框架,及使用VS生成的初始代码基本相同,只有所包含的头文件不同,链接的系统库 ...
- 监控一姐Grafana你可认识?
我们先来认识一下格拉法纳——Grafana. 我去,这不就是实时监控大屏吗?记得 N 年前,部门为了做这么个功能,还花重金请专业公司搞过类似的图,现在想想其实也很简单呀. 话又说回来,其实 Grafa ...
- STM32F103C8T6最小系统开发板原理图
1.
- Scratch 第3课神奇画笔
素材及视频下载 链接:https://pan.baidu.com/s/1qX0T2B_zczcLaCCpiRrsnA提取码:xfp8
- uni_app商城项目(完成)
总结: 1.uni-app的跨段适配性,真的特别强,完成相关代码的书写,HbuilderX编辑器提供的打包十分方便. 2.开发小程序,H5等移动端开发, 比开发电脑端简单不少,但有时候坑也挺多的. 3 ...
- (js描述的)数据结构[树结构1.1](11)
1.树结构: 我们不能说树结构比其他结构都要好,因为每种数据结构都有自己特定的应用场景. 但是树确实也综合了上面的数据结构的优点(当然有点不足于盖过其他的数据结构,比如效率一般情况下没有哈希表高) 并 ...
- 【python实现卷积神经网络】优化器的实现(SGD、Nesterov、Adagrad、Adadelta、RMSprop、Adam)
代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...
- Python pip高级用法
1.pip 高级用法为了便于用户安装和管理第三方库和软件,越来越多的编程语言拥有自己的包管理工 具,如 nodejs 的 npm, ruby 的 gem. Python 也不例外,现在 Python ...
- 16-jmeter-CLI模式(无图形界面)
GUI和非GUI图形界面的使用区别: 非GUI界面:命令模式运行可以将实时的log文件保存到本地,位置可以自定义,不会占用太多资源,可以长时间运行. GUI图形界面:在运行时会消耗资源,且图形界面运行 ...