java中出现的ConcurrentModificationException产生原因,解决方式及其它

JAVA开发中有时会出现ConcurrentModificationException,该异常是由于在遍历Collection的时候做了删除或者增加的操作,此时原来统计的size和新的size并不一致,产生了该异常。下面是stackOverflow上的解释:
[quote]

Here's why: As it is says in the Javadoc:
The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

This check is done in the next() method of the iterator (as you can see by the stacktrace). But we will reach the next() method only if hasNext() delivered true, which is what is called by the for each to check if the boundary is met. In your remove method, when hasNext() checks if it needs to return another element, it will see that it returned two elements, and now after one element was removed the list only contains two elements. So all is peachy and we are done with iterating. The check for concurrent modifications does not occur, as this is done in the next() method which is never called.

Next we get to the second loop. After we remove the second number the hasNext method will check again if can return more values. It has returned two values already, but the list now only contains one. But the code here is:

public boolean hasNext() {
return cursor != size();
}

1 != 2, so we continue to the next() method, which now realizes that someone has been messing with the list and fires the exception.

Hope that clears your question up.[/quote]

要解决该问题,网上也有不少文章。大都谈的是在一个线程中遍历Collection,同时进行删除操作,建议是使用Iterator#remove()方法,而不是其remove(Obj)方法。但如果是多线程的情况下,即使一个线程中使用了Iterator#remove()方法改变了某个Collection,而另一个线程正在遍历该Collection,还是会产生相同的问题。
所以解决办法是需要给两个线程中使用到该Collection的地方都加锁,可以锁定Collection,或者锁定包含Collection的类。

而解决在遍历时会增加的情况,可以将List改为CopyOnWriteArrayList,Map改为相应的同步版本ConcurrentHashMap 即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当遇到 `java.util.ConcurrentModificationException` 异常时,这意味着在迭代集合时,发生了对集合结构的并发修改。这个异常的出现通常有以下原因: 1. 并发修改:在多线程环境下,多个线程同时对同一个集合进行读写操作,而没有使用适当的同步措施。这会导致迭代器的快速失败机制生效,抛出 `ConcurrentModificationException` 异常。 2. 迭代器遍历和修改:在使用迭代器遍历集合时,通过集合的方法(如 `add`、`remove`)直接修改了集合的结构,而不是通过迭代器提供的方法。这会导致迭代器检测到结构上的变化,从而抛出异常。 3. 非并发修改:在单线程环境下,对集合进行迭代的同时,通过其他方式修改了集合的结构。例如,在使用 `for-each` 循环遍历集合时,使用了集合的 `add`、`remove` 方法进行增删操作。 为了解决 `ConcurrentModificationException` 异常,可以考虑以下几种方法: 1. 使用同步机制:在多线程环境下,对共享集合进行读写操作时,使用适当的同步机制(如锁或并发容器)来保证线程安全。 2. 使用迭代器:在遍历集合时,使用集合的迭代器进行操作,并通过迭代器提供的 `remove` 方法来删除元素。这样可以避免直接修改集合的结构。 3. 使用并发容器:如果需要在多线程环境下进行并发修改,可以考虑使用 `java.util.concurrent` 包下提供的并发容器,如 `ConcurrentHashMap` 或 `CopyOnWriteArrayList`,它们提供了线程安全的操作。 4. 使用备份集合:如果需要在迭代集合的同时进行修改,并且不希望抛出异常,可以创建一个备份集合,在备份集合上进行操作,然后再将操作结果复制回原始集合。 综上所述,理解 `ConcurrentModificationException` 异常的原因,并采取适当的解决方法,可以帮助我们编写更稳健的代码。更详细的内容和示例代码,可以参考我为你提供的博客链接:[Java的ConcurrentModificationException异常原因解决方法](https://blog.csdn.net/your-blog-link)。希望对你有所帮助!如有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值