fail fast和fail safe策略
优先考虑出现异常的场景,当程序出现异常的时候,直接抛出异常,随后程序终止
import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; class Main{ public static void main(String[] args) { List<String> list = new ArrayList<>(); Collections.addAll(list,"A","B","C","D"); //modCount = 4,从0开始 Iterator<String> iterator = list.iterator();//取得集合迭代器(取得当前集合的副本),expectedModCount = 4 //当取得集合迭代器的时候(及调用list.iterator()),expectedModCount=modCount while(iterator.hasNext()){ String str = iterator.next();//每次调用这句代码时候 会调用checkForComodification() //以此来检查副本中的expectedModCount是否等于集合中的modCount,为了安全考虑(保证不会脏读) if(str.equals("B")){ //list.remove("B"); //modCount +1=5 ConcurrentModificationException iterator.remove(); continue; } } } }
fail-fast机制
ConcurrentModificationException,Collection集合使用迭代器遍历的时候,使用了集合类提供的修改集合内容方法报错
产生原因:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
collection集合中的modCount表示当前集合修改的次数(remove,add调用的时候,modCount++)
在并发使用的场景中如果发生值的修改保证用户独到的是当前集合的最新值,而不会发生脏读
当取得集合迭代器的时候(及调用list.iterator()),expectedModCount=modCount
换言之,迭代器就是当前集合的一个副本
而如果是有了Iterator迭代器提供的remove()不会出现此错误,本质上在remove时候将modCount重新赋值给expectedModCount
fail safe集合
不抛出此异常的集合
fail-safe:不产生ConcurrentModificationException异常
juc包下线程安全的集合类(CopyOnWriteArrayList、ConcurrentHashMap)
总结:以后在迭代器遍历的时候,不要修改集合的内容
1.为何产生fail fast?
ModCount expectedModCount存在于内部迭代器实现,存储当前集合修改次数
modCount存在于AbstractList记录List集合被修改(add remove)的次数
2.fail fast的意义:保证多线程场景下读取数据不会发生脏读,当有一个线程修改集合的时候,告诉客户端拿到的数据并非最新的
当执行list.remove()的时候,判断元素的下标,使用fastRemove,此时modCount++,不再等于expectedModCount