当集合结构被修改,会抛出Concurrent Modification Exception。 fail-fast会在以下两种情况下抛出ConcurrentModificationException

(1)单线程环境 集合被创建后,在遍历它的过程中修改了结构。  

  注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

(2)多线程环境 当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。

如下:

private static void test0() {

        List<String> list = new ArrayList<>();
list.add("a1");
list.add("a2");
list.add("a3");
list.add("a4");
list.add("a5");
list.add("a6");
list.add("a7");
list.add("a8"); for (String s : list) {
list.remove(s);
} System.out.println(list); }

运行会抛出异常

java.util.ConcurrentModificationException

如果又想在遍历的时候做删除操作呢? 借肋iterator,如下:

private static void test1() {

        List<String> list = new ArrayList<>();
list.add("a1");
list.add("a2");
list.add("a3");
list.add("a4");
list.add("a5");
list.add("a6");
list.add("a7");
list.add("a8"); Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String str = iter.next();
System.out.println(str); //iter.remove();
if (Randoms.random(1, 9) % 2 == 0) {
iter.remove();
}
} System.out.println(list); }

这里我们并没有用list.remove元素而是iter.reomve,但实际list中的元素已经被删除也没有抛异常,为什么会这样?

调试的时候我们发现iter.reomve执行最终调用的是 ArrayList

public E remove(int index)

所以自然影响了原来的集合。

Iterator被创建之后会建立一个指向原来对象的单链索引表, 当list删除元素里不会影响索引,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

我们再看段代码:

private static void test2() {
List list2 = Arrays.asList(new String[]{"a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8",}); Iterator iter2 = list2.iterator(); while (iter2.hasNext()) {
String str = iter2.next(); System.out.println(str); //iter.remove();
if (Randoms.random(1, 9) % 2 == 0) {
iter2.remove();
}
} System.out.println(list2);
}

结果:

会抛出异常java.lang.UnsupportedOperationException

为什么呢?感觉跟test1是一样的?

我们查看源码Arrays:

public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
} /**
* @serial include
*/
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable{...}

发现两个ArrayList并不是同一个类却取了同一个名字:

java.util.Arrays.ArrayList!=java.util.ArrayList

你还是你同一个名字却是另一个他....

java.util.Arrays.ArrayList并没有实现remove方法,所以也就抛出了UnsupportedOperationException 就不足为其了!

看似简单的问题多想一点就好了!

java ConcurrentModificationException探究的更多相关文章

  1. Java ConcurrentModificationException异常原因和解决方法

    Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...

  2. Java并发编程:Java ConcurrentModificationException异常原因和解决方法

    Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...

  3. 【转】Java ConcurrentModificationException异常原因和解决方法

    原文网址:http://www.cnblogs.com/dolphin0520/p/3933551.html Java ConcurrentModificationException异常原因和解决方法 ...

  4. 一种隐蔽性较高的Java ConcurrentModificationException异常场景

    前言 在使用Iterator遍历容器类的过程中,如果对容器的内容进行增加和删除,就会出现ConcurrentModificationException异常.该异常的分析和解决方案详见博文<Jav ...

  5. Java ConcurrentModificationException 异常分析与解决方案

    Java ConcurrentModificationException 异常分析与解决方案http://www.2cto.com/kf/201403/286536.html java.util.Co ...

  6. 9、Java ConcurrentModificationException异常原因和解决方法

    Java ConcurrentModificationException异常原因和解决方法 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会抛出java.u ...

  7. 【转】Java ConcurrentModificationException 异常分析与解决方案--还不错

    原文网址:http://www.2cto.com/kf/201403/286536.html 一.单线程 1. 异常情况举例 只要抛出出现异常,可以肯定的是代码一定有错误的地方.先来看看都有哪些情况会 ...

  8. (转)Java ConcurrentModificationException异常原因和解决方法

    转载自:http://www.cnblogs.com/dolphin0520/p/3933551.html 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会 ...

  9. ConcurrentModificationException探究

    modCount ? 在ArrayList,LinkedList,HashMap等等的内部实现增,删,改中我们总能看到modCount的身影,modCount字面意思就是修改次数 // HashMap ...

随机推荐

  1. ios图片的压缩

    最近做图片的上传,由于项目中的涉及到的图片是从相册和相机中拍照获取的,所以图片的类型不一定,有些是jpg有些是png,另外随着现在设备相继的像素越来越高,所拍摄的图片也越来越到,在图片上传之前我们是需 ...

  2. php数据库常用函数

    //打开mysqlmysql_connect( $host, $user, $pwd ) or die('error');$host => localhost //数据库地址$user => ...

  3. 解決BufferedReader读取UTF-8文件中文乱码

    解決BufferedReader读取UTF-8文件中文乱码         File rst01 = new File(context.getRealPath("/")+" ...

  4. Docker学习笔记整理

    Docker接触有一段时间了,但是对于Docker的使用可以说是一点不会.现在要在Docker上部署基于Angular开发的页面.只能一点点积累查找的资料,顺手整理一下,方便后面的回顾. 其中用到的资 ...

  5. Hyper-V的使用方法

    win8和win8.1以及win10自带虚拟机,无需再装第三方虚拟机软件. 首先需要在“启用或关闭windows功能”中,启用Hyper-V

  6. 关于mvc中@Html.DropDownListFor和@Html.DropDownList默认值无法选中问题简单总结

    当我们在做类似编辑功能的时候,会给定select选中默认值,然而mvc中偶尔这个功能不能用,或者是强类型的@Html.DropDownListFor不能用.凑巧今天遇到问题,解决问题时发现了mvc的一 ...

  7. JS更随机的随机数

    一.问题背景 一个二维平面上有一群NPC,每一回合可以随机向上/下/左/右任一方向走1步,有单位碰撞体积(NPC位置不能重合) 规则就这么简单,初始情况下这群NPC是被人工均匀分布在二维平面上的,运行 ...

  8. NodeJS package.json

    #3 NodeJS package.json 工作目录 package.json 导航至工作目录后,执行下图中的命令

  9. [MFC] 如何更改MFC程序图标

    方法一: >_<:找一张ICO图标,替换programname/res/programname.ico文件,就可以啦,这时候你运行后得到的图标可能还是原来MFC的默认图标,这时候你只要把工 ...

  10. Spring-Context之二:使用Spring提供的测试框架进行测试

    Spring框架是无侵入性的,所以你的代码可以完全是POJO(plain old java object),直接使用Junit就可以完成大部分的单元测试.但是在集成测试方面就比较吃力了.单元测试层面你 ...