Java中的Iterator非常方便地为所有的数据源提供了一个统一的数据读取(删除)的接口,但是在使用的时候容易报如下错误ConcurrentModificationException,原因是在使用迭代器时候底层数据被修改,最常见于数据源不是线程安全的类,如HashMap & ArrayList等。如下代码所示:

public class FailFastDemo {
public static void main(String[] args)throws Exception {
List<Object> objects = new ArrayList<Object>();
objects.add("object1");
objects.add("object2");
objects.add("object3");
Iterator<Object> iterator = objects.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
System.out.println(object);
objects.remove(object);
}
}
}

产生原因

  Java中的集合类分为两种类型:线程安全,位于java.util.concurrent命名目录下,如CopyOnWriteArrayList;线程不安全:位于java.util目录下,如ArrayList,HashMap。所谓线程安全是在多线程环境下,这个类还能表现出和行为规范一致的结果。既然有线程安全的集合,为什么还要使用线程非安全的集合呢呢?因为线程安全的类通常需要通过各种手段去保持对数据访问的同步,会降低数据访问的效率。使用非线程安全的集合类在非并发场景具有很大的优势。如果开发者在使用时没有注意,将非线程安全的集合类用在了并发的场景下,比如线程A获取了ArrayList的iterator,然后线程B通过调用ArrayList.add()修改了ArrayList的数据,此时就有可能会抛出ConcurrentModificationException。
  原理很简单,构建Iterator时将当前ArrayList的modCount保存在expectedModCount之中 ,当下一次调用next()时,会判断ArrayList的modCount值和iterator内部expectedModCount保存的值是否相等。如果相等,说明在遍历的过程中集合类内有发生改变;如果不相等说明在遍历的过程中,集合中的数据发生了改变此时就抛出ConcurrentModificationException。fast-fail是JDK为了提示开发者将非线程安全的类使用到并发的场景下时,抛出一个异常,及早发现代码中的问题。
补充:
  fast-fail的Iterator本身也提供了remove()来删除当前遍历到的元素,例如:ArrayListIterator中的remove(),可以在迭代过程中删除当前数据而不抛出ConcurrentModificationException:

public class FailFastDemo {
public static void main(String[] args)throws Exception {
List<Object> objects = new ArrayList<Object>();
objects.add("object1");
objects.add("object2");
objects.add("object3");
Iterator<Object> iterator = objects.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
System.out.println(object);
iterator.remove();
}
}
}

Fail-Fast机制详解的更多相关文章

  1. 转 Java虚拟机5:Java垃圾回收(GC)机制详解

    转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...

  2. Java SPI机制详解

    Java SPI机制详解 1.什么是SPI? SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制.SPI是一种动态替换发现的机制, 比如有个 ...

  3. 从mixin到new和prototype:Javascript原型机制详解

    从mixin到new和prototype:Javascript原型机制详解   这是一篇markdown格式的文章,更好的阅读体验请访问我的github,移动端请访问我的博客 继承是为了实现方法的复用 ...

  4. 浏览器 HTTP 协议缓存机制详解

    最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag, ...

  5. JVM的垃圾回收机制详解和调优

    JVM的垃圾回收机制详解和调优 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都 ...

  6. ThreadPoolExecutor运转机制详解

    ThreadPoolExecutor运转机制详解 - 走向架构师之路 - 博客频道 - CSDN.NET 最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看 ...

  7. Linux 内存机制详解宝典

    Linux 内存机制详解宝典 在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于 ...

  8. PHP的垃圾回收机制详解

    原文:PHP的垃圾回收机制详解 最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制.本文参考了PHP手册. 在理解PHP垃圾回收机制(GC)之前,先了解一 ...

  9. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  10. Android事件分发机制详解

    事件分发机制详解 一.基础知识介绍 1.经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等 2 ...

随机推荐

  1. win8效果的横向布局

    有一个月没写过博客了,自己的博客也没有看过,前段时间一直在忙着写代码,公司有一个制漆的产品,与传统纵向布局不一样,要求页面横向布局,类似win8的那种布局效果,最开始,我也没有什么头绪,然后硬着头皮做 ...

  2. 【Flex】读取本地XML,然后XML数据转成JSON数据

    干了一年H5,最近被要求写编辑器,Electron等级还不够,写不了,只有重新拿起as3,用flex,最近写到数据表编辑模块,有这部分功能,基本完成 . package utils { /** * 模 ...

  3. Python之路-python介绍

    一.Python及其他语言 有很多种分类方法,其中一种是按照解释型和编译型来划分的. 编译型:例如C,C++ 优点:运行效率高 缺点:依赖编译平台 (不能跨平台,开发效率低) 解释型:例如shell, ...

  4. POPTEST老李谈Debug和Release的区别(c#)

    POPTEST老李谈Debug和Release的区别(c#)   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣 ...

  5. (删)Java线程同步实现二:Lock锁和Condition

    在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...

  6. (iOS)关于@property和@synthesize的理解(原创)

    开始学习ios的时候,就对一些objc的语法不理解,就比如@property和@synthesize,之前都是记住然后照着用,但是写的代码多了,对objc和ios有了一些理解,再加上最近用MRC,所以 ...

  7. Java 基础知识总结

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.数据类型:  数据类型:1>.基本数据类型:1).数值型: 1}.整型类型(byte  8位   (by ...

  8. tr069开源协议EasyCwmp移植

    1.平台MT7628 2.交叉编译器及版本信息mipsel-linux + buildroot-gcc463_32bits.tar.bz2 3.创建工作目录lancer@ubuntu:~$ mkdir ...

  9. 深入解析Hashtable、Dictionary、SortedDictionary、SortedList

    我们先看Hashtable. MSDN的解释:表示键/值对的集合,这些键/值对根据键的哈希代码进行组织. Hash算法是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定 ...

  10. vs2017添加引用时报错未能正确加载“ReferenceManagerPackage”包。

    最近新装了2017,开始前几天还好, 可是最近在添加引用时,报错 ---------------------------Microsoft Visual Studio----------------- ...