栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ConcurrentModificationException并发修改异常源码分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ConcurrentModificationException并发修改异常源码分析

一、引言

我们先来看下面这个程序(修改集合有增添和删除两种,下面是以增添进行分析,删除同理)

public class ListDemo {
    public static void main(String[] args) {
        List list = new ArrayList<>();

        list.add("hello");
        list.add("world");
        list.add("java");

        Iterator it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if ("world".equals(s)) {
                list.add("javaee");
            }
        }
    }
}

运行结果如下

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
	at com.itheima_02.ListDemo.main(ListDemo.java:22)

当我们运行上面程序时,结果会报错ConcurrentModificationException(并发修改异常)


ConcurrentModificationException:当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常。

二、异常源码分析

 1. 根据终端显示的异常信息,可以看到是第22行String s = it.next();的next()方法报错,而这个next()方法是集合list通过调用iterator()方法产生对应迭代器的方法。我们先跟进一下Iterator it = list.iterator();的iterator()方法。

public Iterator iterator() {
        return new Itr();
    }

 2. 可以看到iterator()方法返回一个Iterator实现类对象Itr,再跟进一下Itr类

private class Itr implements Iterator {
        int expectedModCount = modCount;

        @SuppressWarnings("unchecked")
        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();
        }
    }

 3. 从这个Itr内部类可以找到next()方法,执行next()方法的第一条语句是
checkForComodification();我们再跟进一下这个方法

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

 4. 可以看到这个方法做一个判断,判断modCount和expectedModCount是否相等如果不等就会抛出ConcurrentModificationException异常。

modCount:实际集合修改次数
expectedModCount:预期修改次数

 5. 我们看2中的Itr类的第一条语句int expectedModCount = modCount;,这条语句保证了modCount与expectedModCount相等,但是当我们调用list的add()方法时就会修改modCount的值,使得二者不相等,再调用next()进行检查时就会抛出并发修改异常。下面看一下add()方法代码,可以看到在调用add()方法时,第一条语句会让modCount++操作,使得modCount与expectedModCount不相等。

public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }
三、集合的三种遍历方式

并发修改异常通常发生在遍历集合时并对其进行修改,遍历集合有三种方式。


☀️ 第一种:普通for循环

【注释】普通for循环边遍历边修改集合不会出现并发修改异常

public class Test implements I {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("javaee");
        list.add(1, "python");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        
    }
}
☀️ 第二种:增强for循环(推荐使用遍历集合的方式)

【注释】增强for循环底层用的也是集合迭代器进行遍历,所以增强for循环和迭代器循环都会触发并发修改异常。

public class Test implements I {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("javaee");
        list.add(1, "python");
        for (String s : list) {
            System.out.println(s);
        }
    }
}
☀️ 第三种:创建集合迭代器遍历
public class Test implements I {
    public static void main(String[] args) {
        List list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.add("javaee");
        list.add(1, "python");

        Iterator it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/531610.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号