当集合结构被修改,会抛出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. JQuery学习(选择器-基本-*)

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...

  2. 20 个免费的 Bootstrap 的后台管理模板

    之前 OSC 曾经发过多个后台管理界面模板的推荐,例如: 50 个漂亮的后台管理界面模板 25 个精美的后台管理界面模板和布局 分享 6 套超酷的后台管理员界面网站模板 30个优秀的后台管理界面设计案 ...

  3. MariaDB远程连接配置

    由于MariaDB是由MySQL的一个分支发展起来的,二者的配置也大体相同. wex@localhost:~# mysql -uroot -proot 进入MariaDB服务器,将mysql.user ...

  4. 图书馆管理系统—NABCD模型竞争性需求分析

    本次课程设计设计题目:“图书管理系统”主要目的是利用数据库软件编制一个管理软件,用以实现图书.读者以及日常工作等多项管理.同时对整个系统的分析.设计过程给出一个完整论证. 1>N(Need 需求 ...

  5. 布局神器display:table-cell

    元素两端对齐 第一个案例是让两个元素分别向左和向右对齐,如果是过去,我一定会用float来实现,但其实用table可以这么做: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...

  6. [Java拾遗二]Tomact及Http 部分总结.

    前言:   刚好今天回来的很早, 总结下 Tomcat及Http的基础知识. 1, Tomcat    web相关概念        web:网页的意思,网页资源包括服务器上的所有资源.        ...

  7. document对象操作:浏览器页面文件

    //找元素 1.根据id找 <div id="d1" cs="ceshi"><span>document对象</span>& ...

  8. 分享几段JavaScript

    正则表达式 /*http://www.cnblogs.com/woxpp/*/ intege: "^-?[1-9]\\d*$", /*整数*/ intege1: "^[1 ...

  9. iOS开发-【C语言】三目运算符

    1.N目运算符 像逻辑非(!).负号(-)这种只连接一个数据的符号,称为“单目运算符”,比如!5.-5.像算术运算符.关系运算符.逻辑运算符这种连接二个数据的负号,称为“双目运算符”,比如6+7.8* ...

  10. Call and Apply in JavaScript

    Call 和 Apply 方法可以用来代替另一个对象调用一个方法,改变this指向. 1.call -call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) -调用一 ...