ConcurrentModificationException异常

ConcurrentModificationException异常
也叫作并发修改异常
如下:

 ArrayList<String> list = new ArrayList<>();
        list.add("111");
        list.add("222");
        list.add("333");


        System.out.println(list);
        //遍历
        //ConcurrentModificationException 并发(同时  两个以上同时)修改异常
        //操作元素时保证只有一个对象在操作
       Iterator<String> it =  list.iterator();
       while (it.hasNext()){
           String i = (String) it.next();
           System.out.println(i);

           if (i.equals("222")){
               list.remove("222"); //倒数第二个 源码 校验机制(size() -1 ! = 0)=> 执行校验机制
              // it.remove();  //不会出现异常
           }
       }
        System.out.println(list);
        

当运行上述代码时,程序抛出了ConcurrentModificationException异常。
ConcurrentModificationException异常与modCount这个变量有关

modCount的作用。
modCount就是修改次数,在具体的实现类中的Iterator中才会使用。在List集合中,ArrayList是List接口的实现类。

modCount:表示list集合结构上被修改的次数。(在ArrayList所有涉及结构变化的方法中,都增加了modCount的值)

list结构上被修改指的是:改变了list的长度的大小或者是遍历结果中产生了不正确的结果的方式。add()和remove()方法会是的modCount进行+1操作。modCount被修改后会产生ConcurrentModificationException异常, 这是jdk的快速失败原则。

modCount被定义在ArrayList的父类AbstractList中,初值为0,protected transient int modCount = 0。

在进行add()方法是,先调用的ensureCapacity()这个方法,来判断是否需要扩容

在判断是否需要扩容时,用调用ensureExplicitCapacity这个方法,注意,这个方法中对modCount进行的加一操作。所以集合在进行添加元素是会对modCount进行+1的操作。

在进行文章开头的代码时list集合中使用add添加了元素后,size=3,modCount=3。

Iterator的方法是返回了一个Itr()的类的一个实例。

在for循环内部首先对Iterator进行了初始化,初始化。expectedModCount=3,cursor=0。

hasNext是判断是否有下一个元素,判断条件是cursor不等于size,有下一个元素。size=3,cursor=0,是有下一个元素的。

当进行next()方法时,调用了checkForComodification()方法,进行判断是否抛出异常
可以看见进行remove操作时,是通过调用fastRemove()方法进行的实际删除。在fastRemove()方法中,对modCount进行了+1的操作。

此时,modCount=expectedModCount=3,不抛异常,程序继续进行,next()方法有对cursor进行了加一的操作。cursor=1。e=“222”。此时进行remove删除操作。

ArrayList中remove实际在调用fastRemove()方法进行实际的删除,modCount进行了+1操作,modCount=4,size进行了-1的操作,size=2,程序继续进行,cursor=1,size=2,进行next()方法,发现modCount不等于expectedModCount,抛出了ConcurrentModificationException异常。

解决方法:
使用Iterator提供的remove方法,用于删除当前元素。
建立一个集合,记录需要删除的元素,之后统一删除。
不使用Iterator进行遍历,需要注意的是得保证索引正常
使用并发集合类来避免ConcurrentModificationException,比如使用CopyOnArrayList,而不是ArrayList

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值