java - ConcurrentModificationException 和多个 catch block

标签 java concurrentmodification

当我运行以下代码时

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");
        }

    }
}

有人可以解释一下这种行为吗?

最佳答案

让我们看看 documentation :

if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.

请注意,不清楚哪个迭代器方法会抛出异常。让我们检查一下source :

public final boolean hasNext() {
    return next != null;
}

// called by LinkedKeyIterator.next()
final LinkedHashMap.Entry<K,V> nextNode() {
    LinkedHashMap.Entry<K,V> e = next;
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    if (e == null)
        throw new NoSuchElementException();
    current = e;
    next = e.after;
    return e;
}

如您所见,异常是由 next() 方法引发的,而不是由 hasNext() 引发的。由于 four 是集合中的最后一个元素,next 已经为 null,因此对 hasNext() 的下一次调用返回 false 且 next() 不会再次被调用。因此,不会观察到并发修改,也不会抛出异常。

另请参阅Why isn't this code causing a ConcurrentModificationException?

关于java - ConcurrentModificationException 和多个 catch block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44559486/

相关文章:

java - 通过浅拷贝避免 List 上的 ConcurrentModificationException

java - 为什么即使同步了列表也会出现ConcurrentModificationException?

java - 在jsp中的下拉列表中显示数组列表

java - 使用 Spring 和 Maven 的模块化 Web 应用程序

java - 在迭代中从 HashSet 中删除元素

java - 迭代列表时遇到 java.util.ConcurrentModificationException

java - Java中的Iterator如何知道何时抛出ConcurrentModification异常

java - 如何配置 Reactive WebClient 以使用 2-way TLS?

java: NullPointerExc 为什么当直接在其上调用 lambda 表达式时,List 包含添加的对象。当 lambda 是一个方法时则不然

java - Vaadin:将枚举值绑定(bind)到组合框(ConversionException)