码迷,mamicode.com
首页 > 其他好文 > 详细

并发修改异常(ConcurrentModificationException)

时间:2018-08-12 14:21:33      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:昨天   pac   bubuko   源码   last   src   一个   为什么   throw   

并发修改异常(ConcurrentModificationException)

这个异常,使用集合的时候应该很常见,这个异常产生的原因是因为java中不允许直接修改集合的结构。

先贴上个有趣的例子,给你们看看:

package com.xiongda;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Confirm {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("4");
        list.add("3");
        list.add("6");
        Iterator<String> iterator = list.iterator();
        
        while(iterator.hasNext()){
            String integer = iterator.next();
            if(integer.equals("2")) {
                list.remove("2");
            }
                
        }
        
        System.out.println(list.toString());

    }

}

我们使用list的remove方法删除元素,就抛出了这种并发修改异常,如下:

技术分享图片

但是,我们改为判断倒数第二个数,删除任意元素,就不报错了:

package com.xiongda;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Confirm {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("4");
        list.add("3");
        list.add("6");
        Iterator<String> iterator = list.iterator();
        
        while(iterator.hasNext()){
            String integer = iterator.next();
            if(integer.equals("3")) {
                list.remove("2");
            }
                
        }
        
        System.out.println(list.toString());

    }

}

技术分享图片

这是为什么?是不是很神奇?

我昨天研究过源码之后发现,为什么使用arraylist的remove方法会抛出这个异常呢,因为arraylist中的add和remove方法都造成了modcount 和 exceptmodcpiunt不等。

而异常中抛出异常的那个方法checkformodification方法就是检查这两个值知否相等。

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

那么为什么,但判断走到了倒数第二个元素,删除就没有抛出异常了呢?

仔细看抛出的异常,是next方法里面调用的checkformodification方法:

public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

当判断到倒数第二个的时候,remove掉了一个,此时的index和size相等了,就不执行循环了,就不执行next方法了,所以异常就没有抛出来了

public boolean hasNext() {
            return cursor != size;
        }

那么为什么使用迭代器的remove方法不会报错,而使用arraylist的remove方法会报错呢?

这是因为list中的remove方法会使modcount++,但是迭代器中remove方法中多了一条modcount = exceptmodcount语句使其相等,所以使用迭代器不会报错

并发修改异常(ConcurrentModificationException)

标签:昨天   pac   bubuko   源码   last   src   一个   为什么   throw   

原文地址:https://www.cnblogs.com/xtuxiongda/p/9462343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!