概念
Fail-safe 与 fail-fast都是多线程并发操作集合时一种失败的处理机制
fail-fast
表示快速失败,在集合遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出 ConcurrentModificationException异常,从而导致遍历失败。如下:定义个Map集合,使用Iterator迭代器进行数据遍历,在遍历过程中对集合数据做变更时,就会发生fail-fast。
代码如下:
public class Test{
public static void main(String[] args){
Map<String, String> map = new HashMap<String, String>();
map.put("name", "arron");
map.put("sex", "male");
map.put("age", "18");
map.put("address", "beijing");
Iterator iterator = map.keySet().iterator();
while(iterator.hashNext()){
System.out.println(map.get(iterator.next()));
// 在fail-fast机制下,这里会被抛异常 ConcurrentModificationException
mao.put("work", "java");
}
}
}
运行结果如下:
male
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java 1445)
at java.util.HashMap$KeyIterator.nextNode(HashMap.java 1469)
Java.util包下的集合类都是快速失败机制的,不可在多线程下并发使用、并发修改。常见使用fail-fast方式遍历的容器有HashMap 和 ArrayList等。
fail-safe
表示失败安全,在这种机制下出现集合元素修改,也不会抛出ConcurrentModificationException异常。
原理:
1、采用失败安全机制的集合容器,在遍历时不是直接在集合内容访问的,而是先复制原来集合内容,在拷贝集合上进行遍历。
2、迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对元集合进行修改并不能别迭代器检测到。
3、对集合修改后未检测到,不会抛异常,但同时也不会打印出新增或修改的元素。
public class Test{
public static void main(String[] args){
Map<String, String> map = new ConcurrentHashMap<String, String>();
map.put("name", "arron");
map.put("sex", "male");
map.put("age", "18");
map.put("address", "beijing");
Iterator iterator = map.keySet().iterator();
while(iterator.hashNext()){
String str = map.get(iterator.next());
System.out.println(str);
if(str == "18"){
// 在fail-safe机制下,这里不会被打印
mao.put("work", "java");
}
}
}
}
定义一个ConcurrentHashMap集合,在对这个集合遍历过程中,对集合元素进行修改后,不会抛异常,同时也不会打印新增的元素。
Java.util.concurrent包下的容器都是安全失败机制的,可以在多线程下并发使用、并发修改。常见的fail-safe机制遍历的集合有ConcurrentHashMap、CopyOnWriteArrayList等。