`
wsmajunfeng
  • 浏览: 498173 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ConcurrentModificationException

 
阅读更多

如果在获得了某个集合的迭代器之后,除了通过这个迭代器之外对该集合做了结构性的修改(添加元素或删除元素),那么再调用这个迭代器的next()或remove()方法就会抛ConcurrentModificationException异常。

代码如:

写道
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(1));
Iterator<Integer> list1_iterator1 = list1.iterator();
list1.add(2);
list1_iterator1.next();// 此处会抛ConcurrentModificationException

 

又如:

写道
ArrayList<Integer> list2 = new ArrayList<Integer>(Arrays.asList(1));
Iterator<Integer> list2_iterator1 = list2.iterator();
Iterator<Integer> list2_iterator2 = list2.iterator();
list2_iterator1.next();
list2_iterator1.remove();
list2_iterator2.next();// 此处会抛ConcurrentModificationException

 

同样,对Collections.synchronized**()方法返回的线程安全集合类在进行迭代时,发生了上述情况也会抛ConcurrentModificationException。

代码如:

写道
package ConcurrentModificationException;

import java.util.Iterator;
import java.util.List;

/**
* 此任务对迭代器代表的集合做了结构性更改
*/
public class Iterator1 implements Runnable {

private Iterator<Integer> iterator;
private List<Integer> synchronizedList;

public Iterator1(Iterator<Integer> iterator, List<Integer> synchronizedList) {
this.iterator = iterator;
}

@Override
public void run() {
System.out.println("Iterator1 run");
iterator.next();
iterator.remove();
}
}


package ConcurrentModificationException;

import java.util.Iterator;
import java.util.List;

/**
* Iterator1对迭代器代表的集合做了结构性更改
*/
public class Iterator2 implements Runnable {

private Iterator<Integer> iterator;
private List<Integer> synchronizedList;

public Iterator2(Iterator<Integer> iterator, List<Integer> synchronizedList) {
this.iterator = iterator;
}

@Override
public void run() {
System.out.println("Iterator2 run");
iterator.next(); //此处会抛ConcurrentModificationException
}
}


package ConcurrentModificationException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Main {

public static void main(String[] args) {

ArrayList<Integer> list2 = new ArrayList<Integer>(Arrays.asList(1));

final List<Integer> synchronizedList = Collections.synchronizedList(list2);
Iterator<Integer> iterator1 = synchronizedList.iterator();
Iterator<Integer> iterator2 = synchronizedList.iterator();

Thread t1 = new Thread(new Iterator1(iterator1, synchronizedList));// 线程1对迭代器代表的集合(synchronizedList)做了结构性更改
Thread t2 = new Thread(new Iterator2(iterator2, synchronizedList));
t1.start();
t2.start();
}
}

 

 

HashMap API 中指出:

   由所有 HashMap 类的 “collection 视图方法 所返回的迭代器都是快速失败的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException 。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。

   注意,迭代器的快速失败行为不能得到保证,一般来说,存在非同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException 。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics