快速失败(fail-fast)和安全失败(fail-safe)的区别

java.util包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的迭代器永远不会抛出这样的异常。

快速失败示例

public class FailFastTest {
    
    //(01) 新建了一个ArrayList,名称为arrayList。
    private static List<Integer> list = new ArrayList<>();   
    
    public static void main(String[] args) {
        //(02) 向arrayList中添加内容
        for(int i = 0 ; i < 10;i++){
            list.add(i);
        }
        //(03) 新建一个“线程a”,并在“线程a”中通过Iterator反复的读取arrayList的值。
        new threadOne().start();
        //(04) 新建一个“线程b”,在“线程b”中删除arrayList中的一个“节点A”。
        new threadTwo().start();
    }
    
    /**
     * @desc:线程one迭代list
     */
    private static class threadOne extends Thread{
        public void run() {
            Iterator<Integer> iterator = list.iterator();
            while(iterator.hasNext()){
                int i = iterator.next();
                System.out.println("ThreadOne 遍历:" + i);
            }
        }
    }
    
    /**
     * @desc:线程two修改list
     */
    private static class threadTwo extends Thread{
        public void run(){
            int i = 0 ; 
            while(i < 6){
                System.out.println("ThreadTwo run:" + i);
                if(i == 2){
                    list.remove(i);
                }
                i++;
            }
        }
    }
}

fail-fast机制,是一种错误检测机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生。若在多线程环境下使用fail-fast机制的集合,建议使用“java.util.concurrent包下的类”去取代“java.util包下的类”。例如用CopyOnWriteArrayList 来代替ArrayList。

fail-fast产生原因: 在“线程a”在遍历arrayList过程中的某一时刻,“线程b”执行了,并且“线程b”删除了arrayList中的“节点A”。“线程b”执行remove()进行删除操作时,在remove()中执行了“modCount++”,此时modCount变成了N+1
“线程a”接着遍历,当它执行到next()函数时,调用checkForComodification()比较“expectedModCount”和“modCount”的大小;而“expectedModCount=N”,“modCount=N+1”,这样,便抛出ConcurrentModificationException异常,产生fail-fast事件。

从中,我们可以看出:

(01) ArrayList继承于AbstractList,而CopyOnWriteArrayList没有继承于AbstractList,仅仅只是实现了List接口。
(02) ArrayList的iterator()函数返回的Iterator是在AbstractList中实现的;而CopyOnWriteArrayList是自己实现Iterator。
(03) ArrayList的Iterator实现类中调用next()时,会“调用checkForComodification()比较‘expectedModCount’和‘modCount’的大小”;但是,CopyOnWriteArrayList的Iterator实现类中,没有所谓的checkForComodification(),更不会抛出ConcurrentModificationException异常!

原文地址:https://www.cnblogs.com/mcahkf/p/8608468.html