Java fail-fast 机制

简介: fail-fast 机制,即快速失败机制,是 Java 集合(Collection)中的一种错误检测机制,检测在迭代期间集合被修改的情况。fail-fast 机制并不保证在不同步的修改下一定会抛出异常,它只是尽最大努力去抛出,所以这种机制一般仅用于检测 bug。

简介


  fail-fast 机制,即快速失败机制,是 Java 集合(Collection)中的一种错误检测机制,检测在迭代期间集合被修改的情况。fail-fast 机制并不保证在不同步的修改下一定会抛出异常,它只是尽最大努力去抛出,所以这种机制一般仅用于检测 bug


示例


  在集合中,当直接使用 Iterator 迭代(而不是通过 for-each 循环间接使用),对正在被迭代的集合进行结构上的改变(即对该集合使用 addremove clear 等方法),那么迭代器就不再合法,发生 fail-fast,抛出ConcurrentModificationException异常。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);list.add(2);list.add(3);
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
            list.add(4);// 引起fail-fast 
        }
    }
}


原理


  由以上示例,我们通过ArrayList中的Iterator来剖析 fail-fast 机制原理,分析ArrayList中的Iterator如何实现 fail-fast 机制,如何抛出ConcurrentModificationException异常。


调用iterator() 获取Iterator 对象


  它会返回一个 Itr 类的对象,而 Itr 类是 ArrayList 内部类,实现了 Iterator 接口。

public Iterator<E> iterator() {
    return new Itr();// 返回一个Iterator对象
}

Itr 类的成员变量 expectedModCount


  cursor lastRet 都很好理解,我们需要重点关注 expectedModCount,在此之前,我们先搞清楚 modCount 是什么?
  modCount
ArrayList 的一个成员变量,在 ArrayList 被创建即存在并初始化,modCount 含义为记录从创建后 ArrayList 的修改次数,addremove clear 等方法都会引起 modCount 值的增加。
  
在创建了 Itr 对象时,将 modCount 储存在数据域 expectedModCount 中,可以理解为保存 ArrayList 当前状态。

private class Itr implements Iterator<E> {
  int cursor;    // 下一个返回元素的索引,开始为0
  int lastRet = -1; // 最近返回的元素的索引,没有则为-1
  int expectedModCount = modCount;
  ......
}
public E remove(int index) {// ArrayList的remove方法(截取)
  ......
  modCount++;// 每次调用都会增加modCount的值
  ......
}


Itr 类的成员函数 checkForComodification()


  Itr 类中有一个checkForComodification() 方法,专门用于检测最新的 modCount 是否等于expectedModCount,经过前面的分析,可以知道在 ArrayList 进行addremoveclear 等涉及到修改集合结构的操作时,modCount 就会发生改变(modCount++),所以当使用迭代器时改变集合结构或多线程环境中操作集合,就会使 modCount 发生变化,这样在 checkForComodification 方法中就会抛出ConcurrentModificationException 异常。
  
这样即可检测 ArrayList 的状态是否改变过,如果状态改变就抛出 ConcurrentModificationException异常,这样即实现了fail-fast 机制,通过源码可以看出,每一次 next remove 的调用都会调用 checkForComodification 进行检测。

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}
public E next() {
  ......
    checkForComodification();
  ......
}
public void remove() {
  ......
    checkForComodification();
  ......
}

避免 fail-fast


单线程环境


  在单线程的遍历过程中,如果要进行 addremove 等操作,调用迭代器的 addremove 方法而不是集合类的 addremove 方法。


多线程环境

  在多线程环境中使用 Java 并发包(java.util.concurrent)中对应的类来代替ArrayList HashMap  


     比如使用CopyOnWriterArrayList代替 ArrayList,使用ConcurrentHashMap代替 HashMap

相关文章
|
2月前
|
Java API 开发者
深入理解Java中的异常处理机制
本文探讨了Java编程语言中异常处理的核心概念,包括异常类型、异常捕获与抛出、以及最佳实践。通过分析常见的异常场景和处理策略,旨在帮助开发者更好地理解和运用异常处理机制,提高代码的健壮性和可维护性。文章不仅涵盖了基本的try-catch结构,还深入讨论了自定义异常的创建与使用,以及finally块的重要性和应用。此外,还将介绍一些高级技巧,如多异常捕获和嵌套异常处理,为读者提供全面的技术指导。
115 0
|
2月前
|
Java 程序员
深入理解Java异常处理机制
Java的异常处理是编程中的一块基石,它不仅保障了代码的健壮性,还提升了程序的可读性和可维护性。本文将深入浅出地探讨Java异常处理的核心概念、分类、处理策略以及最佳实践,旨在帮助读者建立正确的异常处理观念,提升编程效率和质量。
150 1
|
2月前
|
Java 开发者 UED
深入探索Java中的异常处理机制##
本文将带你深入了解Java语言中的异常处理机制,包括异常的分类、异常的捕获与处理、自定义异常的创建以及最佳实践。通过具体实例和代码演示,帮助你更好地理解和运用Java中的异常处理,提高程序的健壮性和可维护性。 ##
74 2
|
2月前
|
Java 开发者
Java中的异常处理机制深度剖析####
本文深入探讨了Java语言中异常处理的重要性、核心机制及其在实际编程中的应用策略,旨在帮助开发者更有效地编写健壮的代码。通过实例分析,揭示了try-catch-finally结构的最佳实践,以及如何利用自定义异常提升程序的可读性和维护性。此外,还简要介绍了Java 7引入的多异常捕获特性,为读者提供了一个全面而实用的异常处理指南。 ####
98 20
|
2月前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
88 4
|
2月前
|
Java 程序员 UED
深入理解Java中的异常处理机制
本文旨在揭示Java异常处理的奥秘,从基础概念到高级应用,逐步引导读者掌握如何优雅地管理程序中的错误。我们将探讨异常类型、捕获流程,以及如何在代码中有效利用try-catch语句。通过实例分析,我们将展示异常处理在提升代码质量方面的关键作用。
60 3
|
2月前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####
|
3月前
|
运维 Java 编译器
Java 异常处理:机制、策略与最佳实践
Java异常处理是确保程序稳定运行的关键。本文介绍Java异常处理的机制,包括异常类层次结构、try-catch-finally语句的使用,并探讨常见策略及最佳实践,帮助开发者有效管理错误和异常情况。
168 6
|
3月前
|
Java API 数据库
Java 反射机制:动态编程的 “魔法钥匙”
Java反射机制是允许程序在运行时访问类、方法和字段信息的强大工具,被誉为动态编程的“魔法钥匙”。通过反射,开发者可以创建更加灵活、可扩展的应用程序。
83 2
|
3月前
|
Java 开发者
Java中的异常处理机制####
本文深入探讨了Java编程语言中异常处理的核心概念,旨在为开发者提供一套清晰的异常管理策略。不同于传统的摘要概述,本文将通过一个实际案例,逐步揭示如何有效地捕获、处理和抛出异常,以及如何利用自定义异常来增强程序的健壮性和可读性。我们将从基础的try-catch语句出发,逐步深入到finally块的使用,再到throws和throw关键字的区别,最后展示如何创建自定义异常类,以应对特定错误情况。 ####
29 0

热门文章

最新文章