多线程下使用List中的subList和remove方法产生的 java.util.ConcurrentModificationException 异常

news/2024/11/19 17:45:38/文章来源:https://www.cnblogs.com/hhwww/p/18197585

在说多线程操作List之前,我们先看下单线程下产生的问题:

单线程

List<Integer> listA=new ArrayList<>();
listA.add(1);
listA.add(2);
listA.add(3);
listA.add(4);
listA.add(5);
listA.add(6);


for(Integer a:listA){
  if (a==3) {
    listA.remove(3);
  }
}

//再次使用集合就会报错

System.out.println("list元素:" + listA);

该段代码最终会抛出  java.util.ConcurrentModificationException 错误,主要的原因是:

在List循环时,会初始化modCount=0;当该集合进行增加、删除操作值,modCount会自增;而我们使用加强for循环时候,会把modCount初始化的值给迭代器中的expectedModCount,也就是说开始expectedModCount也是为0;但是当集合操作了新增元素,modCount++ ,但是expectedModCount没有新增。导致modCount和expectedModCount不一致,当我们再次访问这个原集合时候,就会抛出java.util.ConcurrentModificationException 错误。

多线程

 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上,对SubList操作,其实也是对ArrayList 操作,比如删除SubList中的元素,同时也会删除ArrayList 的元素。 在subList场景中,高度注意对父集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生 ConcurrentModificationException 异常。

List<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(2);arrayList.add(3);arrayList.add(4);arrayList.add(5);arrayList.add(6);Thread t1= new Thread(new Runnable() {@Overridepublic void run() {List<Integer> list = arrayList.subList(0, 3);for (Integer integer : list) {System.out.println(" "+integer);if(integer == 2){list.remove(integer);}}System.out.println("进行元素的删除操作");//arrayList.remove(4);System.out.println("list元素:" + list);}});Thread t2= new Thread(new Runnable() {@Overridepublic void run() {List<Integer> list2 = arrayList.subList(4, 6);for (Integer integer : list2) {System.out.println(" "+integer);if(integer == 4){list2.remove(integer);}}System.out.println("进行元素的删除操作");//arrayList.remove(4);System.out.println("list元素:" + list2);}});t1.start();t2.start();

 

ArrayList中有个protected transient int modCount = 0; 用来记录当前ArrayList被修改的次数。

比如add(),remove()等都会导致modeCount增加: ArrayList.subList()会生成一个SubList的对象,SubList中有个对应modCount同步ArrayList中的modeCount: SubList对象每次再遍历时,会将自己的modeCount与ArrayList的modeCount进行对比,如果两个值不一样就会报异常:ConcurrentModificationException

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

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

相关文章

KubeKey v3.1 发布:快速自定义离线安装包

日前,KubeKey v3.1 正式发布。该版本主要对离线场景部署、离线包制作以及向 Kubernetes v1.24+ 升级进行了优化。 KubeKey 简介KubeKey 是 KubeSphere 社区开源的一款高效集群部署工具,运行时默认使用 Docker,也可对接 Containerd、CRI-O、iSula 等 CRI 运行时,且 ETCD 集群…

DashVector + ModelScope 玩转多模态检索

本教程演示如何使用向量检索服务(DashVector),结合ModelScope上的中文CLIP多模态检索模型,构建实时的“文本搜图片”的多模态检索能力。作为示例,我们采用多模态牧歌数据集作为图片语料库,用户通过输入文本来跨模态检索最相似的图片。 整体流程主要分为两个阶段: 图片数…

element-plus table部分列根据接口返回key展示

实现效果根据刷选年份返回对应年份作为部分列1. 处理接口数据接口返回数据格式需要处理成   处理过程data.message && data.message.forEach((item:any)=>{let obj = {}for(var key in item){if(Number(key)){Object.assign(obj, {[key]: item[key]})}item.data =…

设计模式05----适配器模式

适配器模式: 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口协同工作。这种模式涉及到一个单独的类,该类负责将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以一起工作。 例如: USB转接口就是适配器,它能够将各种不同类…

基于时间的断路器

1 新建一个微服务模块 我们在cloud-payment-service模块中新增一个controller以提供给其它微服务模块调用。 @RestController public class PayCircuitController {@GetMapping("/pay/circuit/{id}")public String myCircuit(@PathVariable("id") Integer …

计算机体系结构-Booth乘法

本专栏用于记录计算机体系结构学习笔记原理解释 电路实现 以Radix-4 Booth编码为例,Booth乘法的核心是部分积的生成,需要生成\(N/2\)个部分积,每个部分积与\([X]_补\)有关,存在\(-X,-2X,+X,+2X,0\) 这五种可能,其中减去\(X_{补}\)的操作可以认为是按位取反的\(X_{补}\)在末…

使用 JS 实现在浏览器控制台打印图片 console.image()

在前端开发过程中,调试的时候,我门会使用 console.log 等方式查看数据。但对于图片来说,仅靠展示的数据与结构,是无法想象出图片最终呈现的样子的。虽然我们可以把图片数据通过 img 标签展示到页面上,或将图片下载下来进行预览。但这样的调试过程实在是复杂,何不实现一个…

渗透测试快速启动指南-全-

渗透测试快速启动指南(全)原文:Quick Start Guide to Penetration Testing 协议:CC BY-NC-SA 4.0一、NMAP 简介 漏洞评估和渗透测试变得越来越重要,尤其是在最近几年。组织通常拥有存储敏感数据的复杂资产网络。这些资产暴露在来自组织内部和外部的潜在威胁之下。为了全面…

『手撕Vue-CLI』编码规范检查

前言 这篇为什么是编码规范检查呢?因为这是一个很重要的环节,一个好的编码规范可以让代码更加清晰易读,在官方的 VUE-CLI 也是有着很好的编码规范的,所以我也要加入这个环节。 其实不管在哪个项目中,编码规范都是很重要的,像我们平日里的项目开发当中,我们也会使用 ESLi…

字节面试:MySQL什么时候 锁表?如何防止锁表?

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,…

CF1884D Counting Rhyme 题解

题目链接:CF 或者 洛谷 给个莫反题解,讲讲常规套路 题目要求满足没有 \(a_k \mid a_i 与 a_k \mid a_j\) 的 \((i,j)\) 的对数,显然即不存在 \(a_k \mid \gcd(a_i,a_j)\)。稍微拓展下,如果不存在整除多个数,那么显然不整除它们的 \(\gcd\) 即可,因为它们的公因数即为满足…

ITSM工作台:工程师效率与协同的新天地

在当今快节奏的IT运维领域,ITILDESK工作台脱颖而出,成为专为技术工程师量身打造的全能助手。这款平台不仅仅是一个工具集合体,它是一个精心设计的生态系统,旨在促进工程师的工作效率、团队协作与个人成长,为日常运维工作带来前所未有的便捷与智能。 一站式工作环境:从工…