zoukankan      html  css  js  c++  java
  • arrayList里的快速失败

    快速失败是指某个线程在迭代集合类的时候,不允许其他线程修改该集合类的内容,这样迭代器迭代出来的结果就会不准确。

    比如用iterator迭代collection的时候,iterator就是另外起的一个线程,它去迭代collection,如果此时用collection.remove(obj)这个方法修改了collection里面的内容的时候,就会出现ConcurrentModificationException异常,这时候该迭代器就快速失败。

    代码如下:

    package com.vino.assemble;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * show fail fast in in the hashmap
     * @author haowei.yu
     *
     */
    public class FailFastDemo {
        public static void main(String[] args) {
            List<Integer> tempList = new ArrayList<Integer>();
            tempList.add(1);
            tempList.add(2);
            tempList.add(3);
            tempList.add(4);
            tempList.add(5);
            tempList.add(1);
            
            //use iterator to travel the list and remove the value equals to 1
            
            for(int temp: tempList){
                if(temp == 1){
                    tempList.remove(temp);
                }
            }
        }
    }

    这样运行程序,就会抛出java.util.ConcurrentModificationException异常。

    这样做的好处是:对于非并发集合,在用迭代器对其迭代时,若有其他线程修改了增减了集合中的内容,这个迭代会马上感知到,并且立即抛出 ConcurrentModificationException 异常,而不是在迭代完成后或者某些并发的场景才报错。具体这样的机制在java里是怎么实现的呢?其实很简单,是通过modCount域来实现的。modCount顾名思义是修改次数,对List内容的修改都会增加这个值,在迭代器初始化的过程中会将这个值赋值给迭代器的expectedModCount。我们来看ArrayList和Iterator的源码,注释已经写的听清楚了,这里就不解释了。

    //ArrayList的源码
    protected transient int modCount = 0;  //In AbstractList class,provider fail-fast iterators.note that this field is transient
    
    public boolean add(E e) {
        modCount++;  // Increments modCount!!
        .....
        return true;
    }
    
    public E remove(int index) {
        ....
        modCount++; // Increments modCount!!
        .... 
        return oldValue; 
    }
    
    //Iterator的源码
    
    int expectedModCount = modCount; // iterator believes the backing list should hava.
    public void remove() {
        try {
        ....
        if (modCount != expectedModCount)// judge the modCount equals with expectedModCount.
        throw new ConcurrentModificationException();
        ...
        }
    }

    TIPS:

    • 在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出ConcurrentModificationException。
    • 代器的快速失败行为不能得到保证,一般来说,存在非同步的并发修改时,不可能作出任何的保证。快速失败迭代器只是尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。
  • 相关阅读:
    浏览器 窗口 scrollTop 的兼容性问题
    document.documentElement.scrollTop || document.body.scrollTop;
    javascript函数querySelector
    :before和:after的内幕以及伪类
    css伪类伪元素
    JavaScript 运动框架 Step by step
    js中style,currentStyle和getComputedStyle的区别
    js函数变量
    函数
    oracle语法练习
  • 原文地址:https://www.cnblogs.com/babybluevino/p/3695948.html
Copyright © 2011-2022 走看看