java ConcurrentModificationException和多个catch块
当我运行以下代码时
Caught expected ConcurrentModificationException
是打印出来的,这是意料之中的,但奇怪的事情是在第二次迭代中,并没有发现任何异常
Failed to catch expected ConcurrentModificationException
是印刷的。我真的不知道为什么第二次它没有被抓住
public class TestLHS {
public static void main(String[] args) {
LinkedHashSet<Integer> lhSet = new LinkedHashSet<Integer>();
Integer one = new Integer(1);
Integer two = new Integer(2);
Integer three = new Integer(3);
Integer four = new Integer(4);
Integer cinco = new Integer(5);
// Add the three objects to the LinkedHashSet.
// By its nature, the LinkedHashSet will iterate in
// order of insertion.
lhSet.add(one);
lhSet.add(two);
lhSet.add(three);
// 1. Iterate over set. try to insert while processing the
// second item. This should throw a ConcurrentModificationEx
try {
for (Iterator<Integer> it = lhSet.iterator(); it.hasNext();) {
Integer num = (Integer) it.next();
if (num == two) {
lhSet.add(four);
}
System.out.println(num);
}
} catch (ConcurrentModificationException ex) {
System.out.println("Caught expected ConcurrentModificationException");
}
// 2. Iterate again, this time inserting on the (old) 'last'
// element. This too should throw a ConcurrentModificationEx.
// But it doesn't.
try {
for (Iterator<Integer> it = lhSet.iterator(); it.hasNext();) {
Integer num = (Integer) it.next();
if (num == four) {
lhSet.add(cinco);
}
System.out.println(num);
}
System.out.println("Failed to catch expected ConcurrentModificationException");
} catch (ConcurrentModificationException ex) {
System.out.println("Caught expected ConcurrentModificationException");
}
}
}
有人能解释这种行为吗
# 1 楼答案
这是一个编号为6258302的已知问题,发布在JDK错误列表上。在here中也可以找到同样的结果
# 2 楼答案
如果查看LinkedHashMap(或任何实现迭代器的类)的代码,您将看到ConcurrentModificationException在next()方法中被选中
在第一个for循环中得到ConcurrentModificationException,因为当'num'='two'时添加;迭代器还剩下“三个”,所以循环继续。对next()的后续调用是引发异常的地方
在第二个循环中,当最后一个当前元素被迭代时添加,因此不调用next(),也不会抛出ConcurrentModificationException
# 3 楼答案
这一点在Java文档中有明确提到:-
那- 此异常并不总是表示对象已被其他线程同时修改。如果单个线程发出一系列违反对象约定的方法调用,该对象可能会引发此异常。例如,如果线程在使用fail fast迭代器迭代集合时直接修改集合,迭代器将抛出此异常
注意:-不能保证快速失效行为,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬保证。Fail fast operations尽最大努力抛出ConcurrentModificationException。 所以
:-编写依赖于此异常的正确性的程序是错误的:ConcurrentModificationException应该只用于检测错误
更多详细信息请参阅-https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
# 4 楼答案
让我们看看documentation:
请注意,哪个迭代器方法将引发异常并不明确。让我们检查一下source:
如您所见,异常是由
next()
方法引发的,而不是由hasNext()
引发的。由于four
是集合中的最后一个元素,next
已经为空,因此对hasNext()
的下一次调用返回false,并且不再调用next()
。因此,不会观察到并发修改,也不会引发异常另见Why isn't this code causing a ConcurrentModificationException?