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

Java中并发修改异常如何处理

在 Java 中,ConcurrentModificationException(并发修改异常) 是遍历集合时最常见的错误之一。它发生在迭代过程中直接修改集合结构(添加/删除元素)时,与是否多线程无关。以下是详细的处理方案:


一、异常触发场景

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));// 会抛出 ConcurrentModificationException
for (String s : list) {if ("B".equals(s)) {list.remove(s); // 直接调用集合的 remove()}
}

二、解决方案(单线程环境)

1. 使用 Iterator.remove()(推荐)
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {String s = iterator.next();if ("B".equals(s)) {iterator.remove(); // 安全删除当前元素}
}
2. Java 8+ 使用 removeIf()
list.removeIf(s -> "B".equals(s)); // 一行代码解决
3. 使用 CopyOnWriteArrayList(读多写少场景)
List<String> list = new CopyOnWriteArrayList<>(Arrays.asList("A", "B", "C"));
for (String s : list) {if ("B".equals(s)) {list.remove(s); // 安全但性能较低(每次修改复制整个数组)}
}
4. 遍历时记录待删元素,遍历后统一删除
List<String> toRemove = new ArrayList<>();
for (String s : list) {if ("B".equals(s)) {toRemove.add(s);}
}
list.removeAll(toRemove);
5. 使用下标遍历(仅适用于 ArrayList 等随机访问集合)
for (int i = 0; i < list.size(); i++) {String s = list.get(i);if ("B".equals(s)) {list.remove(i);i--; // 修正索引}
}

三、解决方案(多线程环境)

1. 使用并发集合类
// 线程安全的 List
List<String> list = Collections.synchronizedList(new ArrayList<>());// 遍历时需手动同步
synchronized (list) {Iterator<String> it = list.iterator();while (it.hasNext()) {String s = it.next();// 操作元素}
}
2. 使用 java.util.concurrent 包中的集合
// 高性能并发 List
List<String> list = new CopyOnWriteArrayList<>();// 并发 Map
Map<String, String> map = new ConcurrentHashMap<>();
3. 使用锁机制
List<String> list = new ArrayList<>();
ReentrantLock lock = new ReentrantLock();// 写操作加锁
lock.lock();
try {list.add("X");
} finally {lock.unlock();
}// 遍历时加锁
lock.lock();
try {for (String s : list) { /* ... */ }
} finally {lock.unlock();
}

四、关键预防原则

  1. 禁止在遍历中直接修改集合
    使用 iterator.remove() 是唯一安全的修改方式。

  2. 多线程环境优先选并发集合
    ConcurrentHashMap > Collections.synchronizedMap()
    CopyOnWriteArrayList > Collections.synchronizedList()

  3. Java 8+ 优先使用 Stream API

    list = list.stream().filter(s -> !"B".equals(s)).collect(Collectors.toList());
    
  4. 避免在迭代中调用会修改集合的方法
    包括:add(), remove(), clear(), addAll() 等。


五、常见误区

方案问题推荐替代
Collections.synchronizedList()遍历时不同步仍会抛异常遍历时加锁或用 CopyOnWriteArrayList
for 循环删除元素ArrayList 删除后索引错位Iterator.remove() 或倒序遍历
多线程用普通集合 + 同步块易遗漏同步导致并发问题直接使用 ConcurrentHashMap

最佳实践:单线程用 Iterator.remove()removeIf(),多线程用并发集合类,Java 8+ 可配合 Stream API 实现无迭代修改。


文章转载自:

http://kOBplKVA.xLbyx.cn
http://9bJZSGna.xLbyx.cn
http://Qdor6I40.xLbyx.cn
http://GxPWO2Re.xLbyx.cn
http://LbiuZW10.xLbyx.cn
http://kdVrW2sY.xLbyx.cn
http://m9PvS1Ct.xLbyx.cn
http://WFyviwbT.xLbyx.cn
http://qHiT6cjs.xLbyx.cn
http://9r9Fr0n0.xLbyx.cn
http://txQbh1c3.xLbyx.cn
http://UePigkUz.xLbyx.cn
http://HVNPfYhI.xLbyx.cn
http://qDxyh43I.xLbyx.cn
http://qqzpRAc5.xLbyx.cn
http://2uTXolGM.xLbyx.cn
http://me4z1Jvp.xLbyx.cn
http://HJ6THEaE.xLbyx.cn
http://Dfygzc6s.xLbyx.cn
http://7C6Ruuph.xLbyx.cn
http://XlXGnk4o.xLbyx.cn
http://BPNLaMeS.xLbyx.cn
http://MjYISeVX.xLbyx.cn
http://fVNqVPwK.xLbyx.cn
http://a4RsPLlh.xLbyx.cn
http://BCe2eGE6.xLbyx.cn
http://0iFf4gKT.xLbyx.cn
http://LnUGajBT.xLbyx.cn
http://lzSk1Xse.xLbyx.cn
http://M2CjoIxR.xLbyx.cn
http://www.dtcms.com/a/228807.html

相关文章:

  • MaxCompute开发UDF和UDTF案例
  • TDengine 的 AI 应用实战——运维异常检测
  • 软件测试环境搭建与测试流程
  • 新手小白使用VMware创建虚拟机练习Linux
  • C++算法训练营 Day6 哈希表(1)
  • 用AI(Deepseek)做了配色网站-功能介绍【欢迎体验】
  • 人工智能在智能教育中的创新应用与未来趋势
  • “声网AI多语种翻译官:跨境导游的生存革命“
  • Unity UI 性能优化--Sprite 篇
  • Easyui悬停组件
  • 托福39-1 Early Writing Systems感悟
  • 黑客利用GitHub现成工具通过DevOps API发起加密货币挖矿攻击
  • 秋招准备-数据结构
  • 如何安装huaweicloud-sdk-core-3.1.142.jar到本地仓库?
  • Linux 命令全讲解:从基础操作到高级运维的实战指南
  • 滚动部署详解
  • 复杂系统仿真的具体意义
  • 2.3 关于async/await的原理介绍
  • Playwright定位器详解:自动化测试的核心工具
  • 多线程1(Thread)
  • C++语法系列之类型转换
  • 『React』组件副作用,useEffect讲解
  • 12:点云处理—调平,角度,平面度,高度,体积
  • Oracle双平面适用场景讨论会议
  • 【MATLAB代码】制导——三点法,二维平面下的例程|运动目标制导,附完整源代码
  • 【Typst】6.布局函数
  • .Net Framework 4/C# 初识 C#
  • 由docker引入架构简单展开说说技术栈学习之路
  • 基于 NXP + FPGA+Debian 高可靠性工业控制器解决方案
  • Dify知识库下载小程序