说一说Java 迭代器的 Fail-Fast 机制

73 阅读2分钟

文章重点讲解了该机制的原理和如何使用迭代器来提高代码的稳定性和可靠性。文章结合了代码实例,并对每行代码都给出了详细的注释,以便读者更好地理解。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class FailFastIteratorExample {

    public static void main(String[] args) {
        // 创建一个可变大小的列表
        List<String> list = new ArrayList<>();

        // 向列表中添加一些元素
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");
        list.add("Durian");

        // 获取迭代器对象
        Iterator<String> iterator = list.iterator();

        // 迭代并打印列表中的元素
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);

            // 如果在迭代过程中修改了列表结构(如添加或删除元素),将会抛出 ConcurrentModificationException 异常
            // 这是 Fail-Fast 机制的体现,它可以提早检测到并发修改,防止出现潜在的问题
            list.add("Elderberry");
            //如果需要删除则iterator.remove() 便可以不报错进行删除了
            //如果需要新加可以将Iterator<String> iterator = list.iterator(); 换为
            //ListIterator<String> iterator = list.listIterator(); 
            //iterator.add();iterator.set();iterator.remove()来操作元素就不会有问题了
        }
    }
}

这段代码演示了如何使用迭代器来遍历列表并打印其中的元素。在迭代过程中,如果我们尝试在列表结构发生改变时继续修改列表(在这个例子中,我们在每次迭代时都添加了一个新的元素),则会触发 Fail-Fast 机制,抛出 ConcurrentModificationException 异常。

Fail-Fast 机制的原理是在迭代器中维护了一个 modCount 变量,用来记录列表结构发生改变的次数。每次调用迭代器的 next() 方法时,它会检查 modCount 的值是否与列表的 modCount 相等,如果不相等就说明列表发生了结构上的变化,此时迭代器会立即抛出异常以保证数据的一致性。

注意,Fail-Fast 机制并不能保证所有并发修改的错误都能被检测到,它只能在某些情况下提供一种早期检测的机制。因此,在多线程环境下,我们仍然需要采取其他措施来保证数据的一致性和线程安全性。