我是靠谱客的博主 饱满荔枝,最近开发中收集的这篇文章主要介绍java集合之failfast机制,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

failfast机制:快速失败机制。

是java类在应对并发访问在对集合进行迭代过程中,内部对象结构发生变化的一种保护措施,这种错误检测机制为这种有可能发生错误,通过抛出ConcurrentModificationException,防止迭代过程中读到脏数据。

以ArrayList为例:

public class Demo {
    public static void main(String[] args) {

        ArrayList<String> arrayList = new ArrayList<>();

        new Thread(new MyRunnable1(arrayList)).start();
        new Thread(new MyRunnable2(arrayList)).start();

    }

    /**
     * 添加元素的线程
     */
    private static class MyRunnable1 implements Runnable{
        private ArrayList<String> arrayList;

        public MyRunnable1(ArrayList<String> arrayList){
            this.arrayList = arrayList;
        }

        @Override
        public void run() {
            arrayList.add("1");
            arrayList.add("1");
            try {
                //睡眠1秒
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            arrayList.add("1");
            arrayList.add("1");
            arrayList.add("1");
            arrayList.add("1");

        }
    }

    /**
     * 迭代获取元素的线程
     */
    private static class MyRunnable2 implements Runnable{
        private ArrayList<String> arrayList;

        public MyRunnable2(ArrayList<String> arrayList){
            this.arrayList = arrayList;
        }

        @Override
        public void run() {
            Iterator<String> iterator = arrayList.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }

            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while (iterator.hasNext()){
                System.out.println(iterator.next());
            }
        }
    }


}

//这段代码就会抛出该异常,因为在ArrayList对象的迭代过程中有新的线程对他进行了
并发修改。触发了快速失败机制。要用迭代器才会触发,普通的for循环不会触发(foreach会)。实际上是具有快速失败机制的迭代器。

//相应在array中的源码:

private class Itr implements Iterator<E> {
		//游标,当前迭代元素下标
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such

		//创建该迭代器时会把该对象当前的modCount赋值给expectedModCount 。
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
        
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
        //检查是否存在并发修改
final void checkForComodification() {
			//假如另一个线程修改了该对象,modCount 值就会大于expectedModCount,然后抛出异常。
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
}
如何正确的在迭代过程中删除数据。

普通for循环:

public class Demo2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        for (int i = 0;i<5;i++){
            list.add(5);
        }


        for (int i = 0;i<5;i++){
            System.out.println(list.get(i));
            list.remove(i);
        }

    }
}

结果:
在这里插入图片描述
会抛出越界异常,因为删除后,size变小了 但是循环还是5次,所以在循环第四次时就抛出了越界异常,这是不正确的。

使用foreach

public class Demo2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        for (int i = 0;i<5;i++){
            list.add(5);
        }



        for (Integer item:list){
            System.out.println(item);
            list.remove(item);
        }


    }
}

结果:会抛出并发修改异常,也是不对的。
在这里插入图片描述

使用迭代器:

public class Demo2 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();

        for (int i = 0;i<5;i++){
            list.add(5);
        }

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

结果:正确,数据也正常删除了。
在这里插入图片描述

总的来说failfast是比较当前修改次数和期望修改次数不一致时就会抛出异常。

最后

以上就是饱满荔枝为你收集整理的java集合之failfast机制的全部内容,希望文章能够帮你解决java集合之failfast机制所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部