- 浏览: 245747 次
- 性别:
- 来自: 上海
-
文章分类
最新评论
-
di1984HIT:
学习了。
CMS项目中用到的技术(全) -
di1984HIT:
就是用xml麻烦~
RESTEasy入门 -
di1984HIT:
学习了~~
RESTEasy入门 -
真三武侯:
写得很好,感谢分享经验心得!
RESTEasy入门 -
fangcensi:
是不是还有一个application文件,没写出来
RESTEasy入门
为什么会出现 java.util.ConcurrentModificationException 异常?
工作中碰到个ConcurrentModificationException。代码如下:
List list = ...; for(Iterator iter = list.iterator(); iter.hasNext();) { Object obj = iter.next(); ... if(***) { list.remove(obj); } }
在执行了remove方法之后,再去执行循环,iter.next()的时候,报java.util.ConcurrentModificationException(当然,如果remove的是最后一条,就不会再去执行next()操作了)
下面来看一下源码
public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } public interface Collection<E> extends Iterable<E> { ... Iterator<E> iterator(); boolean add(E o); boolean remove(Object o); ... }
这里有两个remove方法
接下来来看看AbstractList
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> { //AbstractCollection和List都继承了Collection protected transient int modCount = 0; private class Itr implements Iterator<E> { //内部类Itr int cursor = 0; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); //特别注意这个方法 try { E next = get(cursor); lastRet = cursor++; return next; } catch(IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); //执行remove对象的操作 if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; //重新设置了expectedModCount的值,避免了ConcurrentModificationException的产生 } catch(IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) //当expectedModCount和modCount不相等时,就抛出ConcurrentModificationException throw new ConcurrentModificationException(); } } } remove(Object o)在ArrayList中实现如下: public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } private void fastRemove(int index) { modCount++; //只增加了modCount .... }
所以,产生ConcurrentModificationException的原因就是:
执行remove(Object o)方法之后,modCount和expectedModCount不相等了。然后当代码执行到next()方法时,判断了checkForComodification(),发现两个数值不等,就抛出了该Exception。
要避免这个Exception,就应该使用remove()方法。
这里我们就不看add(Object o)方法了,也是同样的原因,但没有对应的add()方法。一般嘛,就另建一个List了
下面是网上的其他解释,更能从本质上解释原因:
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator
被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭
代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出
java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
发表评论
-
Java基本功——Reference
2011-10-08 17:52 1166版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声 ... -
Caused by: org.codehaus.jackson.map.JsonMappingException
2011-08-29 16:09 12409写道 No serializer found for cla ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat(2)
2011-08-10 13:44 3902如果能熟练运用这些命令,尤其是在linux下,那么完全可以代替 ... -
JVM监控工具介绍jstack, jconsole, jinfo, jmap, jdb, jstat (1)
2011-08-10 13:44 1214jstack -- 如果java程序崩溃生成core文 ... -
IT公司中最流行的10种编程语言
2011-08-05 13:12 10331. C语言 C语言是一种 ... -
JDK自带线程池总类介绍介绍
2011-07-28 20:38 7881、newFixedThreadPool创建一个指定工作线程数 ... -
深入浅出多线程(4)对CachedThreadPool OutOfMemoryError问题的一些想法
2011-07-28 20:37 1587线程池是Conncurrent包提供给我们的一个重要的礼物。 ... -
Java多线程--让主线程等待所有子线程执行完毕
2011-07-28 19:25 3388数据量很大百万条记录,因此考虑到要用多线程并发执行,在写 ... -
Quartz管理类
2011-07-18 17:11 1262package com.sihuatech.project.t ... -
JAVA写文件到FTP的几种方法
2011-07-18 11:32 26881.使用URL: URL url = n ... -
装饰模式
2011-07-12 11:41 12731) 装饰模式 装饰模式 (Decor ... -
全面解析Java中的String对象的数据类型
2011-07-11 12:56 10611. 首先String不属于8种基本数据类型,String是一 ... -
oscache配置详解
2011-07-08 14:36 2168#一、内存缓存或硬盘、数据库缓存 cache.memory= ... -
oscache使用指南
2011-07-07 15:19 2501一、简介 Cache是一种用于提高系统响应速度、改善 ... -
java文件操作
2011-07-05 12:10 784package Test; import ja ... -
map的三种遍历方法!
2011-07-04 13:27 1029集合的一个很重要的操作---遍历,学习了三种遍历方法,三种 ... -
Java中String类型的参数传递问题的解析
2011-06-29 18:31 1262publicclass StringAsParamOfMeth ... -
not in 优化
2011-06-20 14:35 154301.select * from emp where emp_ ... -
简单工厂模式与策略模式的区别
2011-06-14 16:10 3363工厂(Factory)模式我们可以做如下理解,假设有一个A ... -
UML中的关系
2011-05-30 17:14 956uml定义的关系主要有六种:依赖、类属、关联、实现、聚合和组合 ...
相关推荐
那么,为什么会抛出这个异常呢?我们可以通过查看 ArrayList 的源码来了解原因。ArrayList 的 iterator() 方法返回了一个 Itr 对象,这个对象实现了 Iterator 接口。Itr 对象有三个成员变量:cursor、lastRet 和 ...
java.util.ConcurrentModificationException 解决方法 在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: Java.util....
在Java编程中,`java.util.ConcurrentModificationException` 是一个常见的运行时异常,通常发生在尝试并发修改集合时。这个异常的产生是由于集合类(如HashMap)的非线程安全特性,当你在一个线程中使用迭代器遍历...
其中一个典型的问题就是java.util.ConcurrentModificationException异常,通常在遍历集合时试图修改集合内容时抛出。Java提供了几种解决方案来应对这种情况,以下是详细的解决方法和知识点: ### 并发集合的使用 ...
在Java编程中,`ConcurrentModificationException`是一个常见的运行时异常,主要出现在多线程环境下对集合类(如List、Set、Map等)进行并发修改时。然而,这个异常不仅限于多线程环境,即使在单线程中,如果在遍历...
- **注意事项**:使用`Vector`创建的迭代器时,如果其他线程修改了`Vector`的状态(如添加或删除元素),则可能会抛出`ConcurrentModificationException`异常。 #### 七、`Stack`类 `Stack`继承自`Vector`,实现了...
在进行迭代集合的操作时,如果尝试修改正在迭代的集合结构,如添加或删除元素,Java虚拟机(JVM)会抛出此异常。这个异常对于鸿蒙开发同样适用。要解决这个问题,可以采取以下几种方法: 方法一:使用并发集合类 ...
但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除元素),Iterator将抛出ConcurrentModificationException异常。 Set接口是Collection接口的子接口...
// 在此代码块中进行修改操作不会抛出ConcurrentModificationException异常,因为其他线程无法同时访问该代码块。 list.add("NewElement"); // 添加新元素不会抛出异常 } } finally { lock.unlock(); // 释放锁...
ConcurrentModificationException异常是在Java编程中处理集合时经常会遇到的一个问题。当集合正在被迭代时,如果同时又对其进行修改(比如增加、删除元素等操作),就可能会触发此异常。解决这个问题的方法有很多种...
这是Java中最常见的错误之一,当尝试访问一个为null的对象的成员时,程序会抛出此异常。避免这种问题的方法是始终确保对象在使用前已经被初始化,或者在访问其成员之前进行非null检查。 二、数组越界异常...
在Java编程中,`ConcurrentModificationException`是一个常见的运行时异常,通常发生在多线程环境下对集合进行迭代和修改操作时。此问题的核心在于,Java的集合类(如ArrayList、LinkedList、HashSet等)并不支持...
这种情况下,会出现无法预料的行为或数据不一致的问题。为了避免这类问题,我们探讨了以下几种解决方案。 首先,可以使用迭代器进行迭代和修改集合。当迭代器创建后,你可以在迭代的过程中使用迭代器的 remove() ...
3. 使用并发集合时,可以在迭代过程中安全地修改集合的内容,而不会抛出ConcurrentModificationException异常。比如在ConcurrentHashMap的示例代码中,可以在遍历的同时安全地进行元素的删除操作。 4. 如果由于某些...
java.util.ConcurrentModificationException: mutation occurred during iteration [error] scala.collection.mutable.MutationTracker$.checkMutations(MutationTracker.scala:43) [error] scala.collection....
12. **ConcurrentModificationException**:在并发修改集合时,如果一个线程正在迭代集合,而另一个线程同时对集合进行修改,会出现此异常。推荐使用`CopyOnWriteArrayList`或`ConcurrentHashMap`等并发友好的集合类...
这意味着在多线程环境下,当一个线程正在遍历集合(通过迭代器进行)时,另一个线程修改了集合内容,就会触发快速失败(fail-fast)机制,导致ConcurrentModificationException异常。例如,上述代码中,线程在删除...