Java的ConcurrentModificationException异常介绍和解决方案

news/2025/11/23 22:49:52/文章来源:https://www.cnblogs.com/Lantz12/p/19261765

关于ConcurrentModificationException 异常介绍

在一个线程遍历集合的时候(如ArrayList,HashMap),结构被修改(如remove, add),就会抛出这个异常。

是一个fail fast机制,为了在并发修改的时候发现问题,而不是返回错误数据。

出现的原因

源于ArrayList中的modCount字段

protected transient int modCount = 0;

这个字段的作用是记录结构的修改次数

还有Iterator中的expectedModCount字段,如果expectedModCount不等于modCount,就会抛出CME

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;public void remove() {try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}
}
  • modCount:记录集合被结构修改的次数(add、remove、clear等)
  • expectedModCount:迭代器期望的修改次数

在代码中出现CME的情况

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");for (String s : list) {list.remove(s); // 抛 ConcurrentModificationException
}

以上代码的链表就会发生结构变化,究其根本就是ArrayList修改了但是没有同步到Iterator迭代器,导致modCount != expectedCount从而抛出CME

正确的写法

1)使用Iterator.remove()方法

Iterator<String> it = list.iterator();
while (it.hasNext()) {String s = it.next();if (s.equals("A")) {it.remove();  // ✔ 不会抛 CME}
}

原因是:

public void remove() {// ...code...try {ArrayList.this.remove(lastRet); // 调用集合的removecursor = lastRet;lastRet = -1;expectedModCount = modCount; // 关键:同步更新!} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}
}

2)使用CopyOnWriteArrayList

CopyOnWriteArrayList适合读多写少

List<String> list = new CopyOnWriteArrayList<>();
list.add("A");
list.add("B");for (String s : list) {list.remove(s);  // ✔ 完全没问题
}

因为CopyOnWriteArrayList修改时会创建新的数组,读数据还是遍历旧数组,不会发生CME

3)使用 for 循环倒序遍历

for (int i = list.size() - 1; i >= 0; i--) {list.remove(i); // ✔ 不会 CME
}

4)使用removeIf()

list.removeIf(s -> s.equals("A"));

多线程下出现CME的情况

List<Integer> list = new ArrayList<>();new Thread(() -> {list.add(1);
}).start();new Thread(() -> {for (Integer i : list) {System.out.println(i); // ❌ 可能 CME}
}).start();

解决方案:

使用并发集合:

  1. ConcurrentHashMap
  2. CopyOnWriteArrayList
  3. ConcurrentLinkedQueue
  4. ConcurrentSkipListMap

Fail-fast是什么

指的是程序在运行代码的过程中,如果遇到错误或者异常状态,立即抛出异常停止运行,避免在后续的操作中引发更严重的数据不一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/974317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 Dart 中的 const 与 final:编译时常量与运行时常量

在 Dart 的开发中,我们频繁地使用 const 和 final 来声明变量。表面上看,它们都用于创建“不可变”的变量,但背后的机制却有着本质的区别。这种区别直接影响着程序的性能和内存分配。本文将深入探讨这两者的不同,并…

python: 缩放图片

一,代码 import base64 import cv2 import numpy as np from PIL import Image import io from PIL import Image, ImageFilter from io import BytesIOdata_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhE…

java和python做出什么

Java 和 Python 是两种非常流行的编程语言,它们在不同的应用场景中发挥着重要作用。下面我将从 语言特性、应用场景 和 代码示例 三个方面来详细说明 Java 和 Python 的作用。一、Java 和 Python 的语言特性 1. Java类…

java和linux

Java 和 Linux 是两个不同的技术栈,但它们在系统开发、自动化脚本、服务器管理等领域有密切的联系。以下是关于 Java 和 Linux 的一些关键点和常见用法:一、Java 与 Linux 的关系Java 是一种编程语言,用于开发桌面应…

湖南工程学院 学科实践与创新协会电气部 幕后揭示

第一次为其他学校出的题目~献给挚爱的你的不思议之国幕后揭示 题面地址:https://www.cnblogs.com/Reisentyan/p/19261758 现在时间:\([2025/11/20\) \(23:47]\) 将揭示—— 幕后真相 本场比赛难度预计:Easy - A, …

KEYDIY PAK06-ZB Phone As Key: Replace Your Car Key with Your Smartphone for European/American Cars

The Pain of Traditional Keys: Why Your Garage and Pocket Deserve a Upgrade In the age of smartphones and smart homes, traditional car keys feel increasingly outdated. Whether you’ve mislaid your physi…

湖南工程学院 学科实践与创新协会电气部 新生选拔赛

湖南工程学院新生选拔赛 赛前提醒 在完成本题目时,除抄袭外允许采用任何方式。 最终人员录取将依据所提交代码的质量进行评定,请各位认真对待。 如发现任何抄袭行为,将立即取消参与资格。 题目要求 提交要求 …… 请…

It Calculus

Brownian Motion Wiener Process \(\newcommand{\E}{\mathbb{E}}\newcommand{\Var}{\text{Var}}\)我们熟悉作为离散随机过程的“随机游走”。这指的是:给定一列自然数下标的i.i.d.随机变量\(X_t\),其中\(X_t\)有\(1/…

20232412 2024-2025-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 本实践目标是掌握metasploit的用法。 下载官方靶机Metasploitable2,完成下面实验内容。 (1)前期渗透 (2)Vsftpd源码包后门漏洞(21端口) (3)SambaMS-RPC Shell命令注入漏洞(端口139) (4)Java R…

20232309 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 1.1实验任务前期渗透主机发现(可用Aux中的arp_sweep,search一下就可以use) 端口扫描:可以直接用nmap,也可以用Aux中的portscan/tcp等。 选做:也可以扫系统版本、漏洞等。Vsftpd源码包后门漏洞(21端口…

2025 ICPC 西安区域赛 VP

啊吧啊吧队友是xd和zcr(以后也是),玩的是辅助位,被两位✌带飞了前言 上大学后的第三次线下一起打。 xd之前说肯定会越打越好。 还真是。 记 微积分习题课看完自己的卷子就溜了,然后和zcr一起刷创高,在学校里随机…

K8s学习笔记(二十二) 网络组件 Flannel与Calico - 详解

K8s学习笔记(二十二) 网络组件 Flannel与Calico - 详解2025-11-23 22:30 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; d…

完整教程:人脸识别4-Windows下基于MSVC编译SeetaFace6

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF1483D-Useful Edges

CF1483D-Useful Edges 题目大意 有一个 \(n\) 个结点的无向加权图,以及 \(q\) 个三元组,\((u,v,l)\) ,其中 \(u\) , \(v\) 是顶点,\(l\) 是正整数。 如果存在至少一个三元组和一个具有以下特性的路径(不一定简单…

Paddle-CLS图像分类_环境安装

Paddle-CLS图像分类_环境安装 paddle-cls 图像分类的组件,依赖于`paddle`环境,因此需要先安装`paddle`的环境,而`paddle-cls`对paddle的版本依赖度较高,容易出错,因此建议第一次安装遵循本安装文档,后续再进行其…

2025年11月短视频运营公司最新TOP5推荐:业绩增长与效率筛选标准

随着短视频成为企业数字化营销的核心阵地,市场对专业运营服务商的需求持续攀升。本榜单基于技术创新力、行业适配性、服务效能三大核心维度,结合企业实战案例与客户续约率等关键指标,深度解析2025年云南及西南地区五…

实用指南:【10】MFC入门到精通——MFC 创建向导对话框、属性页类、属性表类、代码

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025-09-10-Wed-T-Kubernetes

1. 介绍说明 1.1 基础设施的变革单机场景单机(操作系统+app)--> 虚拟化(VM+OS+APP) --> 容器化(Container + APP)集群场景 IAAS集群场景 PAASKubernetes优势服务发现和负载均衡 存储编排(添加任何本地或云服…

一文入门 Dify平台的插件开发

一文入门 Dify平台的插件开发 欢迎开始 Dify 插件开发 - https://docs.dify.ai/plugin-dev-zh/0111-getting-started-dify-plugin Dify Plugin 开发速查表 - https://docs.dify.ai/plugin-dev-zh/0131-cheatsheet#环境…

20232326 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1. 实验内容 本实践目标是掌握metasploit的用法。 指导书参考Rapid7官网的指导教程。 https://docs.rapid7.com/metasploit/metasploitable-2-exploitability-guide/ 下载官方靶机Metasploitable2,完成下面实验内容。…