`
chainhou
  • 浏览: 175551 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

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


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.


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

而解决在遍历时会增加的情况,可以将List改为CopyOnWriteArrayList,Map改为相应的同步版本ConcurrentHashMap 即可。
分享到:
评论

相关推荐

    axis1.4.1.zip

    标题“axis1.4.1.zip”所指的是一份针对Axis1.4版本的修复补丁包,这个补丁主要是为了解决在Java Development Kit (JDK) 1.8环境下,高并发场景下出现的`ConcurrentModificationException`问题。`...

    Java多线程安全集合

    在Java编程中,多线程安全集合是程序员在并发环境下处理数据共享时必须考虑的关键概念。这些集合确保了在多个线程访问时的数据一致性、完整性和安全性,避免了竞态条件、死锁和其他并发问题。Java提供了一系列的线程...

    java 面试题 总结

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    各大公司Java后端开发面试题总结

    fail-fast机制是Java集合中的一种快速失败机制,当多个线程对同一个集合进行操作时,如果有其他线程修改了集合的内容,那么通过iterator进行遍历的线程就会抛出ConcurrentModificationException异常,从而保证迭代...

    java数据结构.pdf

    掌握ArrayList的方法,如add、remove、get、set等,以及其与集合框架中其他接口的关系,对于熟练使用Java进行数据处理至关重要。通过实践和深入学习,开发者可以更好地利用数据结构和算法,提高代码的性能和可维护性...

    java面试笔记整理,包含java,redis,kafka等

    ### Java面试知识点详解 #### 一、Java特点 **Java是一种高级编程语言,具有以下特点:** 1. **简单性:** Java设计时考虑到了初学者的需求,语法结构清晰且易于理解。 2. **面向对象:** Java完全支持面向对象编程...

    超级有影响力霸气的Java面试题大全文档

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    深入理解Java之HashMap源码剖析

    此外,HashMap的迭代器(Iterator)是fail-fast的,意味着在迭代过程中,如果其他线程修改了HashMap的结构(添加、删除或修改元素),迭代器会抛出ConcurrentModificationException异常。因此,在多线程环境下,使用...

    HashMap源码剖析共10页.pdf.zip

    HashMap的迭代器是fail-fast的,这意味着在遍历过程中,如果其他线程修改了HashMap,迭代器会抛出ConcurrentModificationException异常。 9. **遍历方式** HashMap提供了两种遍历方式:通过keySet()、entrySet()或...

Global site tag (gtag.js) - Google Analytics