Fail-Safe 迭代 vs Fail-Fast 迭代

Fail-Safe 迭代 vs Fail-Fast 迭代

本文介绍Fail-Safe(安全失败) 和 Fail-Fast (快速失败)概念。

Fail-Safe(安全失败) 机制:尽可能立即暴露故障并停止整个操作。
Fail-Fast (快速失败) 机制: 失败情况下不中断操作,一些系统尝试尽量避免抛出失败异常。

Fail-Fast 迭代

当底层集合被修改时,java中Fail-Fast 迭代会触发。
集合维护内部计数器modCount,每次集合中增加或删除项,计数器会变化。当迭代时,每次调用next()方式时,当前modCount值与最初的modCount值进行比较。如果不匹配,抛出ConcurrentModificationException 异常,中断整个操作。

对java.util package 包中如 ArrayList, HashMap等默认是 Fail-Fast。

ArrayList<Integer> numbers = // ...

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    numbers.add(50);
}

上面代码片段中,在集合修改之后,当下一个next操作开始时会抛出ConcurrentModificationException 异常。
Fail-Fast行为不保证在所有场景都发生,因为并发修改情况下行为不可预测。这些迭代器尽最大努力抛出ConcurrentModificationException 异常。

如果在迭代集合时,通过迭代器的remove方法删除项,是安全的,不会抛出异常。反之,通过集合remove方法删除项则会抛出异常:

ArrayList<Integer> numbers = // ...

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 30) {
        iterator.remove(); // ok!
    }
}

iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 40) {
        numbers.remove(2); // exception
    }
}

Fail-Safe 迭代

Fail-Safe 迭代支持在异常处理不方便时不抛出异常。这些迭代器创建实际集合克隆,基于克隆集合进行迭代。如果迭代器创建之后有任何修改,拷贝版本仍保留未修改的集合。因此,即使集合被修改了,迭代器继续在克隆集合上循环。

然而,需要特别说明的是,没有真正的Fail-Safe 迭代,正确术语应该是弱一致性。这意味着,如果在迭代过程中对集合进行了修改,那么迭代器所看到的是弱保证的。对于不同的集合,这种行为可能是不同的,可以查阅每个集合类的Javadocs。

然而Fail-Safe 迭代有一些缺点,首先是iterator不能保证返回集合更新后的数据。因为其工作在集合克隆上,而非集合本身。其次,创建集合拷贝需要相应的开销,包括时间和内存。

在java.util.concurrent 包中集合迭代器,如 ConcurrentHashMap, CopyOnWriteArrayList等默认为 Fail-Safe。

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.put("First", 10);
map.put("Second", 20);
map.put("Third", 30);
map.put("Fourth", 40);

Iterator<String> iterator = map.keySet().iterator();

while (iterator.hasNext()) {
    String key = iterator.next();
    map.put("Fifth", 50);
}

上面代码片段中,我们使用了Fail-Safe 迭代,因此,即使在迭代过程中集合元素增加了,不会抛出异常。

ConcurrentHashMap的默认迭代器是弱一致的。这意味着这个迭代器可以容忍并发的修改,在迭代器构建时遍历元素,并且可以(但不能保证)在迭代器构建之后反映对集合的修改。

因此,在上面的代码片断中,迭代循环5次,这意味着它确实检测到新添加的元素到集合中。

总结

本文介绍Fail-Safe(安全失败) 和 Fail-Fast (快速失败)概念,以及它们是如何在Java中实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值