Java—— ConcurrentModificationException(并发修改异常)

本文详细介绍了Java中的并发修改异常`ConcurrentModificationException`,主要原因是迭代器在遍历过程中对集合进行修改。文章分析了异常产生的原因,包括modCount变量的作用,并提供了解决方案,如使用`Iterator`的`remove()`方法、`ListIterator`、`removeIf()`方法等。此外,还探讨了多线程环境下如何避免此异常,建议使用同步迭代器或并发容器如`CopyOnWriteArrayList`。
摘要由CSDN通过智能技术生成

一、问题引入

ArrayList的四个基础操作——增删改查

初始化

static ArrayList<Student> students = new ArrayList<Student>();
//初始化
//添加部分学生对象实例
static {
    students.add(new Student("张三", "男", 17));
    students.add(new Student("李四", "男", 18));
    students.add(new Student("王五", "女", 19));
    students.add(new Student("云九", "男", 23));
}

查找:

//查找“云九”
    public static void find(){
        for (Student student : students) {
            if(student.getName().equals("云九")){
                System.out.println(student.toString());
            }
        }
    }

运行结果

 

修改:

//找到“云九”,将其年龄修改为18
 //修改
    public static void modify(){
        for (Student student : students) {
            if(student.getName().equals("云九")){
                student.setAge(18);
                System.out.println(student.toString());
            }
        }
    }

运行结果

 

添加:

//如果有“云九”,则添加一个学生“肖八”
//添加学生
    public static void add(){
        for (Student student : students) {
            if(student.getName().equals("云九")){
                students.add(new Student("肖八", "男", 22));
            }
        }
    }

运行结果

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
    at java.util.ArrayList$Itr.next(ArrayList.java:861)

删除:

//找到“云九”,将其删除
  public static void delete(){
        for (Student student : students) {
            if(student.getName().equals("云九")){
                students.remove(student);
            }
        }
    }

运行结果

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
    at java.util.ArrayList$Itr.next(ArrayList.java:861)

二、原因分析

由此,ArrayList的四种基本操作增删改查,其中的增和删都出现了ConcurrentModificationException,也就是并发修改异常,仔细查看抛出的异常,我们可以发现错误都指向了ArrayList内部类Itr的next方法当中的checkForComodification方法

 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];
        }
final void checkForComodification() {
            if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        }

看到next方法,首先联想到迭代器Iterator,但是以上都是通过for-each进行遍历的,所以这里还涉及到for-each的内部实现问题, for-each的底层其实也是通过迭代器实现的(java foreach内部实现_山间明月江上清风_的博客-CSDN博客),也就是说当我们在使用简洁for循环或者通过迭代器遍历时,都会先调用迭代器的next方法,在next方法中又会首先调用checkForComodification()方法进行检查,当这个方法检查到modCount与expectedModCount不相等时,就会抛出并发修改异常。

由此可知,并发修改异常的实质是一个名为modCount的变量值不再等于expectedModCount的变量值

modCount

 

进一步查看源码可以知道modCount是定义在AbstractList抽象类中的成员变量,而Arra

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值