当集合结构被修改,会抛出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. Week1 Java 基础知识

    JDK=JRE+Tools   JRE=JVM+API 封装:1.模块化:将属性和行为封装在类中,程序定义很多类:2.信息隐蔽:将类的细节部分隐藏起来,用户只通过受保护的接口访问某个类. 继承:父类和 ...

  2. How to Read a Book

    主题: 讲述阅读的四种层次,以及每种层次所需要的.截然不同的阅读方法. 主要声明与论点: 带着问题阅读,时刻不忘在书中寻找问题的答案: 高速阅读,以最短的时间了解一本书的全貌,然后决定是否值得再次阅读 ...

  3. Xamarin开发Android笔记:图片切换ImageSwitcher

    在移动应用开发过程中经常会使用到图片展示场景,例如利用多张图片说明一个产品的特点,此处就会使用到ImageSwithcher,当然也可以使用ViewFliper来实现,但使用ViewFliper的时候 ...

  4. WP8:在Cocos2d-x中使用OpenXLive

    一.    Cocos2d-x for Windows Phone 到2013年底,几大手游引擎都陆续支持WP8了,特别是Unity3D和Cocos2d-x.有过游戏开发经验的朋友们应该对这两个引擎不 ...

  5. [ACM_几何] Transmitters (zoj 1041 ,可旋转半圆内的最多点)

    Description In a wireless network with multiple transmitters sending on the same frequencies, it is ...

  6. [公告]这里的博客将不再更新,最新博客请移步至blog.coderzh.com

    公告:我的博客已迁移至独立博客:http://blog.coderzh.com/  感谢大家支持!同时欢迎关注我的微信公众号:hacker-thinking <---- 扫描左侧二维码关注

  7. 使用grunt打包ueditor源代码

    支持版本支持 UEditor 1.3.0+ 的版本 使用方法1.线上下载ueditor下载地址:ueditor,要下载"完整版 + 源码" 2.安装nodejs下载nodejs并安 ...

  8. dpkg 被中断,您必须手工运行 sudo dpkg -configure -a 解决

    E: dpkg 被中断,您必须手工运行 sudo dpkg --configure -a 解决此问题. E: dpkg 被中断,您必须手工运行 sudo dpkg --configure -a 解决此 ...

  9. windows下安装mysql压缩包版[转]

    版本:5.6.17 1.将解压后的文件夹放到某个目录下,比如c:\software; 2.在环境变量中新建MYSQL_HOME=C:\software\mysql-5.6.17-winx64,然后在系 ...

  10. atitit. hb 原生sql跨数据库解决原理 获得hb 数据库类型运行期获得Dialect

    atitit. hb 原生sql跨数据库解决原理 获得hb 数据库类型运行期获得Dialect   #-----原理 Hibernate 运行期获得Dialect   2010-07-28 12:59 ...