java.util.ConcurrentModificationException

本文深入探讨了Java中ConcurrentModificationException异常的原因及其解决方案。通过具体代码示例,阐述了如何正确使用Iterator进行元素移除操作,避免并发修改引发的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:这已经不是我碰到的第一个bug了···写了一年多的java了,从一无所知慢慢走过来。觉得让自己成长最快的就是这些时不时出现的错误和bug了。现在觉得很有必要将自己遇见的bug,以及出现的bug的原因好好理解并记录了。不能再以简单的解决bug为要求了。顺便也发布到平台上来和大家交流分享。



java.util.ConcurrentModificationException<=========>我叫它:多线程映射索引同步异常(这个命名只是为了让自己念着能第一时间想起这是什么bug。命名无任何考据,诸位见笑了···)


出现bug的代码片段:

/**对用户容器进行遍历,返回一个没有权限为5的用户对象的容器*/

Iterator<UserPo> t = listU.iterator();
while(t.hasNext()){
UserPo ss = t.next();
if(ss.getPower() == 5){
this.ruv.setTeacher(ss);
listU.remove(ss);
}
}


通过自己收集的资料和网上一起其他的解释,出现这个bug的原因是:Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,(个人理解:也就是上述代码中t对象有一个单链表指向listU对象中的位置,遍历会根据这个表去进行遍历。)Iterator当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象(个人理解:我们这里定义ss后面的list对象叫ss1,ss1后面的叫ss2,ss在listU对象的位置是i。当执行了listU.remove(ss)后,在listU中ss对象被删除,listU容器中i位置现在存放的是ss1,i+1的位置存放的是ss2。当进入下次遍历时,Iterator会根据单链表去i+1的位置找ss1,可是此时的i+1的位置存放的是ss2。这与单链表中的记录不一致,因此才会抛出异常),所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。


因此解决上述bug的方法之一是:

Iterator<UserPo> t = listU.iterator();
while(t.hasNext()){
UserPo ss = t.next();
if(ss.getPower() == 5){
this.ruv.setTeacher(ss);
t.remove();
}
}


如果使用增强for循环对listU容器进行遍历,我还没找到办法解决它。这是有同样异常的代码片段:

for(UserPo s:listU){
if(s.getPower() == 5){
this.ruv.setTeacher(s);
listU.remove(s);
}
}


Java.util.ConcurrentModificationExceptionJava编程语言中的一种异常,它通常在并发修改集合时抛出。当使用iterator.hasNext()操作迭代器时,如果在迭代过程中集合发生了改变(如插入或删除元素),就会抛出该异常。该异常的出现原因是由于集合在迭代过程中被修改,导致迭代器检测到并抛出异常。 解决Java.util.ConcurrentModificationException的方法可以通过以下几种途径: 1. 使用Iterator的remove()方法来删除元素,而不是使用集合自身的remove()方法。这是因为Iterator的remove()方法是安全的,可以避免并发修改异常的发生。 2. 使用synchronized关键字或其他同步机制来保证对集合的访问是线程安全的,避免在迭代过程中发生并发修改。 3. 使用并发集合类,如ConcurrentHashMap或CopyOnWriteArrayList,这些类内部使用了一些机制来保证并发修改的安全性,从而避免了ConcurrentModificationException的发生。 总之,要避免Java.util.ConcurrentModificationException异常的发生,需要注意在迭代集合时不要在迭代过程中对集合进行修改,并采取适当的同步机制或使用线程安全的集合类来确保并发修改的安全性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [java.util.ConcurrentModificationException 解决方法](https://download.csdn.net/download/weixin_38723192/14093201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [java.util.ConcurrentModificationException: null 报错解决](https://blog.csdn.net/qq_51741039/article/details/126008727)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值