Java ConcurrentModificationExcepton

2 篇文章 0 订阅
1 篇文章 0 订阅
Java集合遍历中ConcurrentModificationException解决办法

该异常出现的一般原因:不允许的并发修改操作

我们查看Java的API的时候就可以了解到,ConcurrentModificationException是继承了RuntimeException的一个异常,所以它是一个运行时的异常类。通常发生在并发操作’时错误的读写导致的异常错误。这个异常可以通过方法抛出,当探测到对一个对象进行并发修改,然而这个并发修改操作不被允许的时候。


比如说,当一个集合对象是不允许多个线程同时对其进行修改的,当有一个迭代器正在迭代遍历这个集合的时候,如果还有额外的迭代器进行修改操作,这个时候就会报ConcurrentModificationException这个异常。在JDK1.2以及1.2之后就新增了这个异常,至于具体的原因机制可以查看JDK的API文档。点击这里查看1.7版本的JDK。

该异常出现的一般情况:在遍历中对集合中的对象元素进行修改操作

注意:使用迭代器进行遍历,只能通过迭代器进行删除操作,否则则报这个异常,如下:

示例代码1@Test
    public void testCreateConcurrentModificationException() {
        try {
            ArrayList<String> testList = new ArrayList<String>();
            testList.add(new String("One"));
            testList.add(new String("Two"));
            testList.add(new String("Three"));
            Iterator<String> iter1 = testList.iterator();
            for (String str = ""; iter1.hasNext();) {
                str = iter1.next();
                testList.remove(0);
            }
        } catch (ConcurrentModificationException e) {
            e.printStackTrace();
        }
    }

此时,绝对爆出异常:

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    ...
该异常的原理解析:遍历计数器的不均等导致

如示例代码1所示,这里使用的是testList.remove(0);,直接使用原集合对象进行删除操作,这样为什么不行呢,原因很简单,我们不妨看一下ArrayList的源码中的方法:

AbstractList 类的 hasNext()和 next()方法:
public boolean hasNext() {
       return cursor != size();
} 
public E next() {
 checkForComodification();
 try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
  } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
  }
}

final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

所以说,在使用迭代器的时候,next()中调用的checkForComodification(), 在remove方法中也调用了checkForComodification()当进行删除操作的时候,modCount ! =expectedModCount,此时绝对会抛出应有这个异常。总而言之一句话,就是使用那个迭代器时会初始化一个迭代器,使用集合对象本身的add()或者remove()操作的时候也会在内部产生一个迭代器,当在迭代器遍历中使用集合对象删除的时候,里边的modCount会减少,而当使用迭代器的next()方法时,其检测到的modCount和期待的count已经不等了,于是报出这个异常。

该异常的解决方法:在迭代器内部使用迭代器本身进行删除和修改操作
   iterator.remove();

延伸:
集合的拷贝:Java集合中深复制与浅复制


笔者本人相关阅读:
在Github上的静态托管博客1:ALBOG
在Github上的静态托管博客2:Programming Sky
在Github上同步博客阅读:ConcurrentModificationException


欢迎大家阅读本人博客,我是Anderson Lu
October 31, 2015 6:59 PM

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值