java为什么在一个线程迭代(使用迭代器)而另一个线程修改同一个非线程安全ArrayList副本时没有ConcurrentModificationException
一些背景:
当使用Iterator
迭代集合时,可能会出现java.util.ConcurrentModificationException
,因为在创建Iterator
对象时,会捕获集合或数组列表的修改计数(modCount
),并在每次使用Iterator.next()
迭代时检查modCount
是否已更改,如果已更改,则抛出java.util.ConcurrentModificationException
关于创建迭代器对象(来自ArrayList
的Iterator
实现):
int expectedModCount = modCount;
下面的方法被调用Iterator.next()
,它抛出异常(来自ArrayList
的Iterator
实现):
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
我可以用下面的代码很好地复制它:
List<String> stringList = new ArrayList<String>();
stringList.add("a");
stringList.add("b");
stringList.add("c");
Iterator<String> iterator = stringList.iterator();
System.out.println("Got iterator object");
while (iterator.hasNext()) {
String player = iterator.next();
player.toString();
System.out.println("UpperCase: " + player.toUpperCase());
iterator.remove();
stringList.add("a1"); //This is root cause of exception.
}
问题:
- 如果我尝试使用不同的线程(代码如下)修改列表,那么我不会得到
java.util.ConcurrentModificationException
,但是如果我使用相同的线程,那么我会得到异常李>
如果我理解正确,那么在第一个线程的Iterator.next()
的每次传递中,Iterator.checkForComodification()
都会在内部调用,因为我的第二个线程已经修改了列表,所以最新的modCount
将不等于Iterator.expectedModCount
,这是在创建Iterator
对象时初始化的,因此Iterator.checkForComodification()
应该发生异常。对吧
我已经验证了列表正在从线程2更新,线程1的迭代器能够打印新值,因为我可以看到第二个线程正在添加的“d”值
private static void iteratorException() {
final List<String> stringList = new ArrayList<String>();
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("T1");
stringList.add("a");
stringList.add("b");
stringList.add("c");
Iterator<String> iterator = stringList.iterator();
System.out.println("Got iterator object");
while (iterator.hasNext()) {
String player = iterator.next();
player.toString();
System.out.println("UpperCase: " + player.toUpperCase());
iterator.remove();
//stringList.add("a1");
}
}
};
Thread thread2 = new Thread(){
@Override
public void run() {
System.out.println("T2");
stringList.add("d");
stringList.remove("a");
System.out.println("finished T2");
}
};
thread.start();
thread2.start();
}
共 (0) 个答案