快速失败和安全失败

  • java.util 包的集合类就都是快速失败的,如HashMap、ArrayList ;
  • java.util.concurrent 包下的类都是安全失败,比如:ConcurrentHashMap。

1 快速失败(fail-fast)

在使用迭代器对集合对象进行遍历的时候,如果 A 线程正在对集合进行遍历,此时 B 线程对集合进行修改(增加、删除、修改),或者 A 线程自己在遍历过程中对集合进行了修改,都会导致 A 线程抛出 ConcurrentModificationException 异常。

HashMap:

        HashMap<Integer,Integer> map = new HashMap<>();
        map.put(1,2);
        map.put(2,3);

        Set<Map.Entry<Integer, Integer>> set = map.entrySet();

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
     
            map.put(3,4);
            System.out.println(iterator.next());
        }

快速失败和安全失败_第1张图片

List:

 		List<Integer> list = new ArrayList<>();
        list.add(2);
        list.add(3);
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
     
            list.add(4);
            System.out.println(iterator.next());
        }

快速失败和安全失败_第2张图片

迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。

每当迭代器使用 hashNext() 遍历下一个元素之前,都会检测 modCount 变量是否为 原来的值(expectedModCount ),是的话就返回遍历;否则抛出异常,终止遍历。

2 安全失败(fail-safe)

采用安全失败机制的集合容器( java.util.concurrent 包下的类),在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历

由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,故不会抛 ConcurrentModificationException 异常.

	  ConcurrentHashMap<Integer,Integer> map = new ConcurrentHashMap<>();
        map.put(1,2);
        map.put(2,3);

        Set<Map.Entry<Integer, Integer>> set = map.entrySet();

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
     
            map.put(3,4);
            System.out.println(iterator.next());
        }

循环正常执行:

1=2
2=3
3=4

注意:
快速失败和安全失败是对迭代器而言的。

参考博客:https://www.jianshu.com/p/1c73ea87c67d

你可能感兴趣的:(Java常用知识点,java)