- 浏览: 362934 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
July01:
最近了解到一款StratoIO打印控件,功能如下:1、Html ...
js网页打印 -
argel_lj:
littlebitty 写道 嘿嘿,虽说的不好却能解决实际问题 ...
myEclipse设断点进不去 -
argel_lj:
尹宇飞 写道?在那了,找不到不好意思,这个我没有找到官方标准的 ...
word转成XML后,各种标签浅析 -
尹宇飞:
?在那了,找不到
word转成XML后,各种标签浅析 -
littlebitty:
...
myEclipse设断点进不去
工作中碰到个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去除字符串中的空格、回车、换行符、制表符 .
2013-05-09 10:35 1416import java.util.regex.Matcher; ... -
关于事务
2012-12-19 16:36 0一、何为事务? 事 ... -
Java中类与对象的生命周期
2012-11-08 16:34 1112类的生命周期 .java源文件经过编译后会生成相应的字节 ... -
java类成员变量的生命周期
2012-11-08 16:06 0引子.. 看如下一段代码: private ... -
JDBC复习
2012-07-05 15:49 1325一,JDBC的编程步骤: --学自尚学堂 1. ... -
try 、catch、throw、throws深入探究
2012-06-26 14:02 1276关键字浅析 throws是用来声明一个方法可能抛出的所 ... -
java中如何遍历一个map
2012-05-07 16:07 1131java遍历map方法如下 for(Map.Entry ... -
jvm参数配置
2012-04-17 10:53 1513常见JVM参数配置汇总 堆设置 -Xms:初始堆 ... -
java获取日期
2012-03-19 22:28 8501 如何获取当前年份? new Date ... -
过滤字符串中的空格 小结
2012-03-14 17:18 11991 trim() 2 全角、半 ... -
java中getRemoteAddr()方法获取客户端IP地址问题解决方案
2012-03-08 14:03 2161在JSP里,获取客户端的IP地址的方法是:request. ... -
关于java继承的一些思考
2012-03-01 17:28 994子类继承父类 属性和方法怎么使用? ... -
关于JAVA数组
2012-01-10 19:42 888今天,遇到一个问题要让把LIST转成数组,经TE ... -
org.springframework.jdbc.CannotGetJdbcConnectionException:
2011-12-24 09:26 2390org.springframework.jdbc.Cannot ... -
myEclipse设断点进不去
2011-12-12 17:05 9668web开发中,有时在myeclipse中 ... -
java.lang.OutOfMemoryError: Java heap space
2011-11-17 16:05 1952java.lang.OutOfMemoryError: Jav ... -
如何取一组数据中的最大值(数组、集合)
2011-11-02 17:42 1913public static void main(S ... -
JDBC 之ResultSet
2011-09-29 13:52 21092ResultSet简介: ... -
java 文件学习(待续)
2011-09-17 17:46 9781、IO中什么是流,为什么要引入流 ? ... -
Java代码风格规范(分享)
2011-09-16 19:03 5132介绍(Introduction) 为什么要有编码规范(W ...
相关推荐
Java.util.ConcurrentModificationException 异常问题详解 ConcurrentModificationException 异常是 Java 中一个常见的异常,它发生在 Iterator 遍历集合时,集合同时被修改引起的异常。在 Java 中,集合类如 ...
在Java编程中,`java.util.ConcurrentModificationException` 是一个常见的运行时异常,通常发生在尝试并发修改集合时。这个异常的产生是由于集合类(如HashMap)的非线程安全特性,当你在一个线程中使用迭代器遍历...
`java.util.ConcurrentModificationException` 是一个在 Java 中常见的运行时异常,它通常发生在多线程环境中,当一个线程正在遍历一个集合(如 `ArrayList`, `HashMap` 等),而另一个线程同时尝试修改这个集合时。...
### Java.util.concurrent 系列文章知识点总结 #### 一、引言 随着多核处理器的普及,多线程编程已成为现代软件开发中的一个重要组成部分。Java 5 引入了 `java.util.concurrent` 包,该包提供了丰富的 API 来简化...
在Java编程中,`ConcurrentModificationException`是一个常见的运行时异常,主要出现在多线程环境下对集合类(如List、Set、Map等)进行并发修改时。然而,这个异常不仅限于多线程环境,即使在单线程中,如果在遍历...
Java语言的Util类详细介绍 Java语言的Util类是Java开发中非常重要的一部分,它提供了一系列的类来实现基本的数据结构,如线性表、链表等。这些类均在java.util包中。 Collection接口是Java中最基本的集合接口,一...
Spring数据mongodb测试 在Collections.synchronizedList或Collections.synchronizedSet上测试spring数据mongodb ConcurrentModificationException
java.util.ConcurrentModificationException: mutation occurred during iteration [error] scala.collection.mutable.MutationTracker$.checkMutations(MutationTracker.scala:43) [error] scala.collection....
使用`synchronized`关键字、`volatile`变量、`java.util.concurrent`包中的工具类等可以有效地管理并发。 四、内存泄漏 Java中的内存泄漏并不像C++那样直接导致资源耗尽,但过度持有对象引用会导致垃圾收集器无法...
否则将会引发 java.util.ConcurrentModificationException 异常。 3. Iterator 迭代器采用的是快速失败(fail-fast)机制,一旦在迭代过程中检测到该集合已经被修改(通常是程序中其它线程修改),程序立即引发 ...
- `java.util.Iterator`的改进:支持`remove()`操作,避免抛出`ConcurrentModificationException`。 ### 4. 性能优化 JDK 1.6对编译器和垃圾收集器进行了优化,提高了运行效率,例如: - **Server VM的改进**: ...
需要注意的是,在迭代的过程中不能对集合中元素进行修改,否则将产生 java.util.ConcurrentModificationException。 选择集合 在实际开发中,选择合适的集合是非常重要的。以下是一些选择集合的建议: * 如果需要...
import java.util.ArrayList; import java.util.Iterator; public class IteratorExample { public static void main(String[] args) { ArrayList<String> names = new ArrayList(); names.add("Ada Lovelace");...
Java的`java.util.concurrent`包提供了更为高效且专门设计用于并发操作的集合。比如: - `ConcurrentHashMap`:线程安全的哈希映射,比`synchronized Map`性能更好,因为它允许不同部分独立加锁,减少了锁竞争。 ...
4. 如果需要更复杂的并发控制,可以使用`java.util.concurrent.locks`包下的Lock接口及其实现,如ReentrantLock,配合`tryLock()`方法进行细粒度的锁控制。 总的来说,处理多线程环境中的Java集合类时,开发者需要...
java中,List在遍历的时候,如果被修改了会抛出java.util.ConcurrentModificationException错误。 看如下代码: import java.util.ArrayList; import java.util.List; public class Resource3 { public ...
在Java编程语言中,集合框架(`java.util`包)提供了多种容器类来存储对象,如`List`、`Set`和`Map`等。为了遍历这些容器中的元素,Java引入了迭代器模式(Iterator Pattern),这是一种常用的设计模式,它提供了一...
当多个线程同时调用`add`方法时,可能会抛出`java.util.ConcurrentModificationException`异常。 **4.2 解决方案** - 使用`Vector`类代替`ArrayList`,因为`Vector`的所有公共方法都进行了同步处理,但这种方法降低...