当前位置: 首页 > news >正文

java迭代集合出现并发修改异常(ConcurrentModificationException)的原因以及解决方案

java迭代集合出现并发修改异常(ConcurrentModificationException)的原因以及解决方案

一. 什么时候会出现并发修改异常?

这里先看需求 : 定义一个集合,存储 唐僧,孙悟空,猪八戒,沙僧,遍历集合,如果遍历到猪八戒,往集合中添加一个白龙马

很显然要求我们先创建一个集合并进行迭代 , 当迭代到猪八戒,的时候插入白龙马

代码实现

public static void main(String[] args) {//需求:定义一个集合,存储 唐僧,孙悟空,猪八戒,沙僧,遍历集合,如果遍历到猪八戒,往集合中添加一个白龙马ArrayList<String> list = new ArrayList<>();list.add("唐僧");list.add("孙悟空");list.add("猪八戒");list.add("沙僧");Iterator<String> iterator = list.iterator();while(iterator.hasNext()){String element = iterator.next();if ("猪八戒".equals(element)){list.add("白龙马");}}System.out.println(list);}

运行后报错

在这里插入图片描述

这里报了一个ConcurrentModificationException 也就是并发修改异常

二. 产生原因

我们来进入源码分析一下

  1. 首先我们来进入 iterator() 方法 , 这里iterator() 是返回了了一个新对象也就是Itr() , 那我们再来看一下Itr()方法

    public Iterator<E> iterator() {return new Itr();}
    
  2. Itr() , 光观察Itr()好像并没有发现异常的原因 , 那我们再看next()方法

    private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;// prevent creating a synthetic constructorItr() {}public boolean hasNext() {return cursor != size;}
  3. next() , 这里在运行next()的时候会先调用checkForComodification();方法那我们就先来查看这个方法

    @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];}
    
  4. checkForComodification() , 很显然这里判断了modCount 与 expectedModCount是否相等 , 如果不相等则抛出throw new ConcurrentModificationException(); 也就是并发修改异常

    modCount: 实际操作次数
    expectedModCount:预期操作次数

     final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}
    
  5. 那么通过上面的分析我们就知道了产生问题的原因是什么 , 也就是modCount 与 expectedModCount并不相等

    那是什么导致modCount 与 expectedModCount不相等的呢 ? 在代码中我们调用了一个add方法 , 那么add是否就是产生问题的原因

  6. add() , 还是和刚才一样 , 进入add()底层源码我们来找一下原因

    public boolean add(E e) {modCount++;add(e, elementData, size);return true;}
    

    到这里就一目了然了我们在调用add的时候会对modCount++ , 在modCount自增之后 , 我们再调用next()方法就会导致modCount 与 expectedModCount不相等 , 从而抛出异常

三. 解决方法

ArrayList中的方法:ListIterator listIterator()

public class Demo03Iterator {public static void main(String[] args) {//需求:定义一个集合,存储 唐僧,孙悟空,猪八戒,沙僧,遍历集合,如果遍历到猪八戒,往集合中添加一个白龙马ArrayList<String> list = new ArrayList<>();list.add("唐僧");list.add("孙悟空");list.add("猪八戒");list.add("沙僧");//Iterator<String> iterator = list.iterator();ListIterator<String> listIterator = list.listIterator();while(listIterator.hasNext()){String element = listIterator.next();if ("猪八戒".equals(element)){listIterator.add("白龙马");}}System.out.println(list);}
}
http://www.lryc.cn/news/405860.html

相关文章:

  • BGP选路之Local Preference
  • WEB渗透信息收集篇--IP和端口信息
  • 国内微短剧系统平台抖音微信付费小程序app开发源代码交付
  • Java语言程序设计基础篇_编程练习题**15.19 (游戏:手眼协调)
  • 学习记录day16—— 数据结构 双向链表 循环链表
  • Air780EP模块 AT开发-MQTT接入OneNET移动物联网平台应用指南
  • HOST处理器预读PCI设备
  • 【Ansible】通过role角色部署lnmp架构
  • springboot给属性赋值的两种方式(yaml与properties)
  • 20240725 每日AI必读资讯
  • 17_高级进程间通信 UNIX域套接字1
  • 大型语言模型的生物医学知识图优化提示生成
  • winform datagrid 全部勾选
  • 从 NextJS SSRF 漏洞看 Host 头滥用所带来的危害
  • LC617-合并二叉树
  • 深入解析:端到端目标检测模型的奥秘
  • xmind--如何快速将Excel表中多列数据,复制到XMind分成多级主题
  • 在 Android 上实现语音命令识别:详细指南
  • 怎么理解FPGA的查找表与CPLD的乘积项
  • 51.2T 800G 以太网交换机,赋能AI开放生态
  • 【制作100个unity游戏之31】用unity制作一个爬坡2d赛车小游戏
  • Spring Boot 注解 @PostConstruct 介绍
  • 深度学习环境配置报错解决日记
  • 百度,有道,谷歌翻译API
  • java-双亲委派机制
  • 【C++】set的使用
  • React 18【实用教程】(2024最新版)
  • Perl语言入门学习指南
  • 《Java8函数式编程》学习笔记汇总
  • C语言之封装,继承,多态