什么是 Fail-Fast 和 Fail-Safe?🤔
在 Java 中,当我们使用迭代器(Iterator)遍历集合时,有两种处理方式:
- Fail-Fast(快速失败):如果你在遍历集合的同时修改了它,迭代器会立刻报错,抛出
ConcurrentModificationException
,让你知道出了问题。🚨💥 - Fail-Safe(安全失败):即使你在遍历的同时修改了集合,迭代器仍然会继续工作,它不会报错,因为它会工作在原始数据的副本上。📋🔒
Fail-Fast 和 Fail-Safe 的区别👇:
1. Fail-Fast(快速失败)🚨
- 定义:当你用迭代器遍历一个集合时,如果同时修改了这个集合,迭代器会立刻报错,程序就会“快速失败”。
- 代表:
ArrayList
是典型的 Fail-Fast 集合。如果你在遍历ArrayList
时试图修改它,比如添加或删除元素,程序会立刻抛出ConcurrentModificationException
。 - 为什么?🤔:这是为了防止在遍历时修改集合导致数据不一致的问题。如果你正在数清楚一堆苹果🍎,有人在你数的时候偷偷拿走或增加几个,你就乱套了,对吧?Fail-Fast 就是为了解决这种问题。
示例代码:Fail-Fast 的情况:
import java.util.ArrayList;
import java.util.Iterator;
public class FailFastExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
Iterator<String> iterator = list.iterator();
// 在遍历的时候修改了集合,这会导致 Fail-Fast 🚨
while (iterator.hasNext()) {
System.out.println(iterator.next());
list.add("Pineapple"); // 尝试修改集合
}
}
}
结果:
这个代码会抛出 ConcurrentModificationException
,因为我们在遍历的时候往集合里添加了元素🍍。
2. Fail-Safe(安全失败)🔒
- 定义:当你用迭代器遍历一个集合时,如果你同时修改了集合,不会报错,而是继续遍历。原因是 Fail-Safe 的迭代器会遍历集合的副本,而不是原始集合。
- 代表:
CopyOnWriteArrayList
是典型的 Fail-Safe 集合。它会创建一个副本,在你遍历的同时修改原集合不会影响遍历过程。 - 为什么?🤔:这种机制保证了程序的稳定性🔒,即使在多线程环境下,也不会因为集合的修改导致遍历错误。
示例代码:Fail-Safe 的情况:
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.Iterator;
public class FailSafeExample {
public static void main(String[] args) {
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");
Iterator<String> iterator = list.iterator();
// 在遍历的时候修改集合,不会报错 ✅
while (iterator.hasNext()) {
System.out.println(iterator.next());
list.add("Pineapple"); // 可以在遍历时添加元素
}
}
}
结果:
这个代码不会抛出异常,程序会继续运行,因为 CopyOnWriteArrayList
使用了副本,遍历时不会受到原集合修改的影响。
Fail-Fast 和 Fail-Safe 的对比 🆚
特性 | Fail-Fast 🚨 | Fail-Safe 🔒 |
---|---|---|
代表集合 | ArrayList , HashMap | CopyOnWriteArrayList , ConcurrentHashMap |
遍历时修改 | 报错 ConcurrentModificationException | 不报错,安全遍历 |
如何实现 | 直接遍历原集合 | 通过副本来遍历集合 |
效率 | 快速,但容易出错 | 稳定,但内存开销大 |
总结💡:
- Fail-Fast(快速失败):如果你在遍历时修改集合,它会立刻报错,常见于
ArrayList
。 - Fail-Safe(安全失败):即使在遍历时修改集合,它也不会报错,常见于
CopyOnWriteArrayList
,因为它遍历的是集合的副本。