fail-fast
fail-fast的字面意思是快速失败。当在遍历集合元素时,经常会使用迭代器,但在迭代器遍历元素的过程中,如果集合的结构被改变的话,就会抛出异常,防止继续遍历。这就是所谓的快速失败机制。
fail-fast即快速失败机制,它是java集合中的一种错误检测机制,当多个线程(当个线程也是可以),在结构上对集合进行改变时,就有可能会产生fail-fast机制。
当Iterator这个迭代器被创建后,除了迭代器本身的方法(remove)可以改变集合的结构外,其他的因素如若改变了集合的结构,都被抛出ConcurrentModificationException异常。ListIterator---list
原理:modCount和Iterator实现类中的expectedModCount
fail-safe与fail-fast的区别
当我们对集合结构上做出改变的时候,fail-fast机制就会抛出异常。但是,对于采用fail-safe机制来说,就不会抛出异常。这是因为,当集合的结构被改变的时候,fail-safe机制会在复制原集合的一份数据出来,然后在复制的那份数据遍历。因此,虽然fail-safe不会抛出异常,但存在以下缺点:
1. 复制时需要额外的空间和时间上的开销。
2. 不能保证遍历的是最新内容。
- Java.util包中的所有集合类都被设计为fail-fast快速失败,java.util.concurrent 中的集合类都为
fail-safe安全失败的
- Fail-fast迭代器抛出ConcurrentModificationException,Fail-safe迭代器从不抛出ConcurrentMod
ificationException
- 安全失败Fail-Safe 类型的数据结构,当集合对象发生结构性修改时不会抛出任何异常。这是因为迭代器在执行开始前,基于原集合类元拷贝了一份元素副本,因此迭代器执行的操作,如遍历、添加或删除等,并非原集合类对象的内部元素
集合容错总结
Fail Fast 迭代器的几个关键点:
- 遍历时一旦发现原集合对象发生修改则会抛出 ConcurrentModificationException
- 被遍历的是原集合对象的元素
- 这类迭代器不需要额外内存空间
Fail Safe 迭代器的几个关键点:
- 允许在进行迭代时对原集合对象的元素进行修改
- 在遍历的同时修改集合对象的元素,不会抛出任何异常
- 一种实现是:遍历的是原集合类对象元素的拷贝,需要额外的内存空间用于拷贝的元素数组。另一种实现是:weakly consistent,内存弱一致性。
数据结构
Fail-Fast
- ArrayList、LinkedList、Vector【虽然是线程安全的】
- HashSet、LinkedHashSet、TreeSet
- HashMap、LinkedHashMap、TreeMap、Hashtable【虽然是线程安全的】
- Collections.synchronizedXXX() 包装出的【虽然是线程安全的】
Fail-Safe
- CopyOnWriteArrayList
- CopyOnWriteArraySet
- ConcurrentSkipListSet
- ConcurrentHashMap