fail-safe和fail-fast机制-爱代码爱编程
01 fail-safe和fail-fast
fail-safe和fail-fast ,是多线程并发操作集合时的一种失败处理机制。
02 Fail-fast (快速失败)
在集合遍历中,一旦发现容器中数据被修改了,立刻抛出ConcurrentModificationException,从而导致遍历失败
java.util包下的集合类都是快速失败机制的, 常见的的使用fail-fast方式遍历的容器有HashMap和ArrayList等
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("11", "22");
map.put("33", "44");
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
System.out.println(map.get(iterator.next()));
map.put("55", "66");
}
}
输出
22
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$KeyIterator.next(HashMap.java:1466)
at com.test.Test.main(Test.java:28)
03 Fail-safe(失败安全)
集合元素修改,不会抛出异常
,原因是采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,
在拷贝的集合上进行遍历。由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到
比如这种情况(贴下面这个图) , 定义了一个CopyOnWriteArrayList,在对这个集合遍历过程中,对集合元素做修改后,不会抛出异常,但同时也不会打印出增加的元素。
java.util.concurrent包下的容器都是安全失败的,可以在多线程下并发使用,并发修改。
常见的的使用fail-safe方式遍历的容器有ConcerrentHashMap和CopyOnWriteArrayList等
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList();
copyOnWriteArrayList.add(1);
copyOnWriteArrayList.add(2);
copyOnWriteArrayList.add(3);
Iterator<Integer> iterator = copyOnWriteArrayList.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println(next);
// 这个地方不会抛异常
copyOnWriteArrayList.add(4);
}
Thread.sleep(1000);
System.out.println("----------------");
// 这里打印出来的还是旧的集合
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println(next);
}
Thread.sleep(1000);
System.out.println("----------------");
// 这里打印出来的是新的集合
Iterator<Integer> iterator1 = copyOnWriteArrayList.iterator();
while (iterator1.hasNext()) {
Integer next = iterator1.next();
System.out.println(next);
}
}
输出
1
2
3
1
2
3
4
4
4