当前位置: 首页 > article >正文

Java中快速失败 (fail-fast) 机制

快速失败 (fail-fast) 是什么?

fail-fast 是一种错误检测机制,它的核心思想是在检测到错误条件时立即抛出异常,以防止程序进一步执行可能导致错误的操作。通常用于迭代器以及集合类中。当你用迭代器对集合进行迭代时,如果集合在迭代过程中被修改了,就会立即抛出ConcurrentModificationException。这种修改可能是添加、删除集合中的元素。快速失败机制通过立即通知程序员发生了并发修改,避免了未定义行为的出现。

案例 1

public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        
        // 创建迭代器
        Iterator<Integer> iterator = numbers.iterator();
        // 在迭代器创建后对列表进行修改
        numbers.add(4);
        // 再次输出迭代器的值
        while (iterator.hasNext()) {
            System.out.println(iterator.next()); // 第一次进来时报错
        }
    }
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
	at java.util.ArrayList$Itr.next(ArrayList.java:861)
	at org.swp.controller.UserContext.main(UserContext.java:15)

迭代器创建之后,通过调用numbers.add(4)修改了列表的结构,从而在随后的迭代中引发了ConcurrentModificationException

案例 2

public static void main(String[] args) {
	ArrayList<Integer> numbers = new ArrayList<>();
	numbers.add(1);
	numbers.add(2);
	numbers.add(3);
		// 其实在代码编译的时候for循环会被编译成迭代器
	for(Integer a : numbers){ // 第二次遍历时报错
		if(a.equals(1)){
			numbers.remove(a);
		}
	}
}
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
	at java.util.ArrayList$Itr.next(ArrayList.java:861)
	at org.swp.controller.UserContext.main(UserContext.java:15)

当迭代器正在遍历numbers列表时,你尝试从中删除元素。这会改变列表的结构,因此触发了ConcurrentModificationException

如何避免这个异常

要修复这种错误,你需要确保在迭代期间不直接修改集合。如果你必须修改集合,你有几个选项:

  • 在迭代期间收集要删除的元素,然后在迭代后删除它们。
  • 使用迭代器提供的remove()方法来移除元素。
  • 使用支持并发修改的集合类,如ConcurrentHashMap或CopyOnWriteArrayList。
  • 在for循环中引入变量,而不是遍历集合
ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        for(int i=0;i<list.size();i++) {
            Integer item = list.get(i);
            if (item.equals(3)) {
                list.remove(i);//为了效率,这里最好不要用list.remove(item)
            }
        }

不引用迭代器方法进行删除,可以防止ConcurrentModificationException

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer a = iterator.next();
    if (a.equals(1)) {
        iterator.remove();
    }
}

使用迭代器的remove()方法来删除当前元素可以防止ConcurrentModificationException,因为这样做不会破坏迭代器的内部状态。

public static void main(String[] args) {
        CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer a = iterator.next();
            if (a.equals(1)) {
                list.remove(a);
            }
        }
        System.out.println(list);
    }

CopyOnWriteArrayList 源码推荐阅读文章
文章链接: 解析CopyOnWriteArrayList的高效读取与安全更新


http://www.kler.cn/a/159091.html

相关文章:

  • Go 语言已立足主流,编程语言排行榜24 年 11 月
  • 牛客挑战赛77
  • Python学习笔记(2)正则表达式
  • 推荐15个2024最新精选wordpress模板
  • 利用Blackbox AI让编程更轻松
  • 图形几何之美系列:二维凸包艺术赏析
  • 装修流程篇
  • C++ 预处理详解
  • Siemens-NXUG二次开发-打开与关闭prt文件[Python UF][20231206]
  • IBNR详解及基于R的计算逻辑
  • Python 元组详解(tuple)
  • python字符串格式化--数字精度控制和快速写法
  • 安装npm,配置国内源
  • WebDriver运行原理的深入剖析
  • scipy
  • 基于高德API实现网络geoJSON功能(整体)
  • Qlik 成为网络犯罪的焦点
  • 图像识别经典轻量级网络模型总结梳理、原理解析与优劣对比分析
  • 机器学习中Fine-tuning应用实例
  • AVFormatContext封装层:理论与实战
  • 今日心得:多总结多探索,多于他人沟通,思想观点碰撞
  • Lambda表达式与方法引用
  • java8 常用code
  • Gitee项目推荐-HasChat
  • 28、卷积 - 卷积的基础公式
  • 前端笔记:React的form表单全部置空或者某个操作框置空的做法