面试准备--快速失败和安全失败

329 阅读1分钟

快速失败 fail-fast

在使用迭代器对于集合对象遍历,如果对集合进行了修改(添加、删除、修改),都会导致抛出ConcurrentModificationException异常。
java.util包下的集合都是快速失败。

List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
        list.add(4);
}

执行后效果如下:

快速失败的原因:
在生成iterator是,会将ArrayList的modCount赋值给expectedModCount。 当iterator在执行next()、remove()方法是,会判断expectedModCount与modCount是否相等。若不相等,则抛出ConcurrentModificationException异常。

public E next() {
    checkForComodification();
    ...
}

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();
   ...
}

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

当ArrayList在进行新增、删除、修改操作时,会改变modCount的值。再使用iterator遍历的时候,就会抛出异常。

安全失败 fail-safe

遍历时不在原集合上遍历,而是先复制原集合内容,在拷贝的集合上进行遍历。
java.util.concurrent包下的集合都是安全失败的。

List list = new CopyOnWriteArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    Iterator iterator = list.iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
        list.add(4);
    }

执行结果如下,遍历时。并不知道改变后的list。