文章目录

  • 简介
  • 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:

  1. 单线程的环境中

如果在单线程的环境中,iterator创建之后,如果不是通过iterator自身的remove方法,而是通过调用其他的方法修改了集合的结构,则会报错。

  1. 多线程的环境中

如果一个线程中创建了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知多少相关推荐

  1. Fail Fast与Fail Safe的区别

    Fail Fast Fail Fast Iterator在遍历集合时,若该集合发生了结构性的改变,则将抛出 ConcurrentModification 异常.例如: Map<String, S ...

  2. 什么是Fail Fast和Fail Safe?

    这里是目录标题 1. Fail Fast a. 概念 b. 原理 c. 关注点 d. 注意 2. Fail Safe a. 概念 b. 原理 3. Fail Fast 和 Fail Safe的区别 1 ...

  3. fail safe java_Java中快速失败(fail-fast)和安全失败(fail-safe)的区别?

    快速失败(fail-fast): 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加.删除.修改),则会抛出Concurrent Modification Exception ...

  4. 网络安全架构部署:Fail Closed,Fail Open,Fail safe,Fail over是什么意思?

    目录 1.Fail Closed(故障关闭) 故障关闭的用例和好处 部署故障关闭注意事项 2.Fail Open(故障打开) 故障打开的用例及好处 部署故障打开注意事项 3.Fail Safe(故障保 ...

  5. 什么是fail safe IO

    背景 普通IO cell,内置二极管用作ESD保护. 考虑一种应用场景,当芯片只有部分上电的时候.芯片部分IO,是断开电源. 如果芯片IO外接设备,输入给芯片高电平,会导致二极管导通,使得芯片内电源异 ...

  6. 车辆控制器的 Fail Safe功能介绍

    Fail Safe概要 在漆黑的夜路上,一辆开着头灯的汽车经过. 如果控制前照灯的控制器在这种情况下发生故障怎么办? 大灯会熄灭,造成危险吗? 不. 在这种情况下,控制器的"Fail Saf ...

  7. 小程序上传文件报错uploadFile:fail url scheme is invalid,uploadFile:fail createUploadTask:fail Error: Invalid

    今天在这里记录一个很蠢的问题. 问题 最近用小程序的上传文件 API(wx.uploadFile) 上传音频,这个 API 说白了就是比 wx.request 多带了个请求头 multipart/fo ...

  8. 微信小程序上传文件报错: errMsg: “uploadFile:fail createUploadTask:fail invalid url“

    errMsg: "uploadFile:fail createUploadTask:fail invalid url" invalid url: 无效的url 在控制台打印出url ...

  9. Java - Java集合中的安全失败Fail Safe机制 (CopyOnWriteArrayList)

    文章目录 Pre 概述 fail-safe的容器-CopyOnWriteArrayList add remove函数 例子 缺陷 使用场景 Pre Java - Java集合中的快速失败Fail Fa ...

  10. 程序设计思想之故障安全(fail safe)

    有"故障安全"的基本设计思想.然而,许多人对故障安全有很大的误解. 为了确保安全性,使其具有双重三重.多重功能,而不是"故障安全".所谓故障安全,机器.系统和其 ...

最新文章

  1. python兼职程序员工资一般多少-做Python程序员,工资一般多少?
  2. flask执行python脚本_如何在flask后端运行python脚本?
  3. java 导入world数据_java读取world文件,把world文件中的内容,原样输出到页面上。...
  4. ubuntu16.04更改python版本
  5. 基于FPGA实现Aurora高速串行接口
  6. javaEE版eclipse设置默认编码格式为utf-8
  7. STM32 - Cube介绍
  8. 手机算通用计算机还是,通用盾是一种u盾。手机和电脑都可以用。问一...
  9. 如何评价兰州交通大学的软件工程专业?
  10. 为什么再次调用编辑器总是加载同一张图片?
  11. Django基础(29): select_related和prefetch_related的用法与区别
  12. 后台开发面试要点(腾讯互娱事业群)
  13. CVTE面试总结(全网面经,已收offer)
  14. JS的特性:异步 + 事件驱动
  15. 卡尔曼滤波室内温度估计
  16. 2021年森林督查暨森林资源管理“一张图”更新工作方案
  17. 【机器学习】树模型预剪枝和后剪枝
  18. Bootstrap—实现圆角、圆形头像和响应式图片
  19. 关于谭浩强老先生的《C++程序设计教程》
  20. python推箱子代码详细讲解_Python使用tkinter模块实现推箱子游戏

热门文章

  1. 导入技能要素三大类_教学技能之导入技能(值得收藏)
  2. 内存泄露、内存溢出以及解决方法
  3. Web安全实践(14)嗅探,arp欺骗,会话劫持与重放攻击(下)
  4. 2021大厂面试高频100题最新汇总(附答案详解)
  5. 学会查看 RabbitMQ日志
  6. 云游戏之大冒险:5G,等还是不等 | 专访云格致力陈浩
  7. Pinterest:Android系统上的视频管理
  8. 腾讯云实时音视频技术发展简史 — 从编解码器容错优化到云端决策系统
  9. 李幸原:看好实时音视频在教育与医疗的前景
  10. Facebook批量优化360照片