关于list的ConcurrentModificationException 异常

原创 2016年05月31日 12:10:59

ConcurrentModificationException–java.lang.RuntimeException,一个运行时错误。
此类在源码中的注解为:
/**
* An {@code ConcurrentModificationException} is thrown when a Collection is
* modified and an existing iterator on the Collection is used to modify the
* Collection as well.
*/
意思大致为:在一个集合被修改以及一个现有的集合的迭代器被用于修改此集合时会抛出一个此异常。

下面从List开始分析,List是Java中的一个Interface(接口),List中定义了add()、get()、contain()、remove()、iterator()等方法(iterator()方法返回的为一个Iterator对象)。List接口被AbstractList实现,此类为一抽象类(从1.2版本开始出现,ArrayList并不是直接实现List接口),ArrayList继承AbstractList具体重写了add()等方法,同时ArrayList中有一内部类ArrayListIterator,此类具有hasNext()与next()方法。

使用Iterator与foreach循环list原理都是使用的ArrayListIterator,执行ArrayListIterator的hasNext()与next()方法。

@Override public Iterator<E> iterator() {
        return new ArrayListIterator();
    }

ArrayListIterator中的hasNext()与next()方法为:

public boolean hasNext() {
            return remaining != 0;
        }

@SuppressWarnings("unchecked") public E next() {
            ArrayList<E> ourList = ArrayList.this;
            int rem = remaining;
            if (ourList.modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            if (rem == 0) {
                throw new NoSuchElementException();
            }
            remaining = rem - 1;
            return (E) ourList.array[removalIndex = ourList.size - rem];
        }

hasNext()方法中的remaining值初始为list大小,随着每循环一次,该值会在next()方法中减1,直至为0,hasNext()方法返回false,也就不再执行next()方法。
next()方法中会判断ourList.modCount的值与expectedModCount值是否相等,其实异常的根源就出自于此,expectedModCount是ArrayListIterator的一个属性,初始化被赋予modCount的值。
这里写图片描述
而modCount为AbstractList属性,值为list的大小,此变量在remove()方法中执行的++操作,因此如果在foreach或者使用Iterator循环中对除最后一个元素之外的其他元素执行remove()操作,modCount的值会被改变,从而在next()方法中的

if (ourList.modCount != expectedModCount) {
     throw new ConcurrentModificationException();
}

判断会抛出ConcurrentModificationException。

此异常也有特例,上边说了对除最后一个元素之外的元素执行remove操作才会报异常,那么如果是对最后一个元素执行删除操作呢?答案是不会抛出异常的,虽然modCount变量值在remove()方法中改变了,但在循环到最后一个元素时remaining的值已经变为了0,所以hasNext()方法返回true,不在执行next()方法,因此不在抛出异常。

关于此异常还是有解决办法的,Java中提供有CopyOnWriteArrayList,可以使用此类代替ArrayList,关于CopyOnWriteArrayList会在之后进行分析。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

关于List的ConcurrentModificationException

对ArrayList的操作我们可以通过索引象来访问,也可以通过Iterator来访问,只要不对ArrayList结构上进行修改都不会造成ConcurrentModificationException,...
  • wwbmyos
  • wwbmyos
  • 2012年08月20日 16:19
  • 22056

Java 遍历List ConcurrentModificationException 异常解析

ConcurrentModificationException 异常解析

List remove时出错"ConcurrentModificationException"

1. 现象: 在遍历list的时候,出现错误
  • liranke
  • liranke
  • 2014年04月28日 18:15
  • 2519

ArrayList 使用迭代抛出ConcurrentModificationException解决方法

注意,ArrayList实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,而其中至少一个线程从结构上修改了列表,那么它必须 保持外部同步。(结构上的修改是指任何添加或删除一个或多个元...
  • xyylchq
  • xyylchq
  • 2012年08月15日 15:54
  • 4386

java.util.ConcurrentModificationException详解

【引言】 经常在迭代集合元素时,会想对集合做修改(add/remove)操作,类似下面这段代码: for (Iterator it = list.iterator(); it.hasNext();...
  • SMCwwh
  • SMCwwh
  • 2011年12月03日 00:07
  • 36124

List的add方法报空指针异常

/**      * 查询好友列表      */     @Override     @ResponseBody     public JSONArray queryFriendList(...

DataGridView绑定List<T>,出现IndexOutOfRangeException异常

最近在测试系统的时候DataGridView出现IndexOutOfRangeException异常,对DataGridView绑定的数据源类型是List。由于DataGridView我使用的是第三方...

遍历List集合的时候删除单个(多个)元素(解决并发异常)

Exception in thread "main" java.util.ConcurrentModificationException

页游服务器开服异常Check List

最近由于迎接我们游戏《凡*传》公司内测,提前准备了个Checklist,以便自己参考,现共享给大家. 经常性的开服第一天是服务器压力较大的,玩家大批量涌入,大批量下载客户端资源,如果准备不足的话,多少...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于list的ConcurrentModificationException 异常
举报原因:
原因补充:

(最多只允许输入30个字)