fail-safe fail-fast知多少
文章目录
- 简介
- Fail-fast Iterator
- Fail-fast 的原理
- Fail-safe Iterator
- 总结
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 exceptionwhile (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 exceptionwhile (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 exceptionwhile (iterator1.hasNext()){log.info("{}",users.get(iterator1.next()));users.put(2, "mark");}Iterator iterator2 = users.keySet().iterator();//modify key,get exceptionwhile (iterator2.hasNext()){log.info("{}",users.get(iterator2.next()));users.put(4, "mark");}
上面的例子完美执行,不会报错。
总结
Fail-fast 和 Fail-safe 是集合遍历的重要概念,希望大家能够掌握。
本文的例子 https://github.com/ddean2009/learn-java-streams
更多精彩内容且看:
- 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
- Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
- Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
- java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程
欢迎关注我的公众号:程序那些事,更多精彩等着您!
更多内容请访问 www.flydean.com
fail-safe fail-fast知多少相关推荐
- Fail Fast与Fail Safe的区别
Fail Fast Fail Fast Iterator在遍历集合时,若该集合发生了结构性的改变,则将抛出 ConcurrentModification 异常.例如: Map<String, S ...
- 什么是Fail Fast和Fail Safe?
这里是目录标题 1. Fail Fast a. 概念 b. 原理 c. 关注点 d. 注意 2. Fail Safe a. 概念 b. 原理 3. Fail Fast 和 Fail Safe的区别 1 ...
- fail safe java_Java中快速失败(fail-fast)和安全失败(fail-safe)的区别?
快速失败(fail-fast): 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exception ...
- 网络安全架构部署:Fail Closed,Fail Open,Fail safe,Fail over是什么意思?
目录 1.Fail Closed(故障关闭) 故障关闭的用例和好处 部署故障关闭注意事项 2.Fail Open(故障打开) 故障打开的用例及好处 部署故障打开注意事项 3.Fail Safe(故障保 ...
- 什么是fail safe IO
背景 普通IO cell,内置二极管用作ESD保护. 考虑一种应用场景,当芯片只有部分上电的时候.芯片部分IO,是断开电源. 如果芯片IO外接设备,输入给芯片高电平,会导致二极管导通,使得芯片内电源异 ...
- 车辆控制器的 Fail Safe功能介绍
Fail Safe概要 在漆黑的夜路上,一辆开着头灯的汽车经过. 如果控制前照灯的控制器在这种情况下发生故障怎么办? 大灯会熄灭,造成危险吗? 不. 在这种情况下,控制器的"Fail Saf ...
- 小程序上传文件报错uploadFile:fail url scheme is invalid,uploadFile:fail createUploadTask:fail Error: Invalid
今天在这里记录一个很蠢的问题. 问题 最近用小程序的上传文件 API(wx.uploadFile) 上传音频,这个 API 说白了就是比 wx.request 多带了个请求头 multipart/fo ...
- 微信小程序上传文件报错: errMsg: “uploadFile:fail createUploadTask:fail invalid url“
errMsg: "uploadFile:fail createUploadTask:fail invalid url" invalid url: 无效的url 在控制台打印出url ...
- Java - Java集合中的安全失败Fail Safe机制 (CopyOnWriteArrayList)
文章目录 Pre 概述 fail-safe的容器-CopyOnWriteArrayList add remove函数 例子 缺陷 使用场景 Pre Java - Java集合中的快速失败Fail Fa ...
- 程序设计思想之故障安全(fail safe)
有"故障安全"的基本设计思想.然而,许多人对故障安全有很大的误解. 为了确保安全性,使其具有双重三重.多重功能,而不是"故障安全".所谓故障安全,机器.系统和其 ...
最新文章
- python兼职程序员工资一般多少-做Python程序员,工资一般多少?
- flask执行python脚本_如何在flask后端运行python脚本?
- java 导入world数据_java读取world文件,把world文件中的内容,原样输出到页面上。...
- ubuntu16.04更改python版本
- 基于FPGA实现Aurora高速串行接口
- javaEE版eclipse设置默认编码格式为utf-8
- STM32 - Cube介绍
- 手机算通用计算机还是,通用盾是一种u盾。手机和电脑都可以用。问一...
- 如何评价兰州交通大学的软件工程专业?
- 为什么再次调用编辑器总是加载同一张图片?
- Django基础(29): select_related和prefetch_related的用法与区别
- 后台开发面试要点(腾讯互娱事业群)
- CVTE面试总结(全网面经,已收offer)
- JS的特性:异步 + 事件驱动
- 卡尔曼滤波室内温度估计
- 2021年森林督查暨森林资源管理“一张图”更新工作方案
- 【机器学习】树模型预剪枝和后剪枝
- Bootstrap—实现圆角、圆形头像和响应式图片
- 关于谭浩强老先生的《C++程序设计教程》
- python推箱子代码详细讲解_Python使用tkinter模块实现推箱子游戏