您的位置:首页 > Web前端

fail-fast 与 fail-safe

2019-08-01 07:17 1996 查看

快速失败(fail-fast)与安全失败(fail-safe)

fail-fast:当再遍历集合(以非线程安全的HashMap为例)的时候,如果监测到modCount值发变化,则直接抛出ConcurrentModificationException的异常,如果是使用迭代器遍历时修改,会在第一次的时候将异常抛出,如果是用forEach循环的话,则会在执行完所有的代码后再抛出异常(以前的for(Object object : list)的语法方式,经过编译之后变成迭代器iterator,但java8的foreach编译之后并不会变成迭代器iterator,而是编译后的结果与编写时几乎一样,所以java8的foreach可能不是纯粹是语法糖)

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

// 测试一,当执行第一个的时候就会报错,不会执行下一个
Set set = hashMap.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
hashMap.put(10, 10);
System.out.println("此时 hashMap 长度为" + hashMap.size());
}
// 测试一结果:
//        1=1
//        此时 hashMap 长度为4
//        java.util.ConcurrentModificationException

// 测试二,用原始的for循环进行遍历,测试结果同测试一,原因其实时for是语法糖,编译后就会变化迭代器
Set<Integer> keySet = hashMap.keySet();
for (Integer index : keySet) {
System.out.println(hashMap.get(index));
hashMap.put(10, 10);
System.out.println("此时 hashMap 长度为" + hashMap.size());
}

// 测试三,会执行完for的所有代码,最后再抛出异常,java8的循环已经不同于迭代器
hashMap.forEach((o, o2) -> {
System.out.println(String.valueOf(o) + String.valueOf(o2));
hashMap.put(4, 4);
System.out.println("此时 hashMap 长度为" + hashMap.size());
});

// 测试三结果:
//        11
//        此时 hashMap 长度为4
//        22
//        此时 hashMap 长度为4
//        33
//        此时 hashMap 长度为4
//        44
//        此时 hashMap 长度为4
//        java.util.ConcurrentModificationException

fail-safe(针对线程安全的集合,例如:ConcurrentHashMap)

网上解释:当在做遍历的时候,集合会复制出一份,再做遍历,这样即使原集合做了修改,也不会影响当前遍历,即遍历有三个元素的集合,在遍历期间,添加了一个元素,在遍历过程中,添加后的元素不会被遍历到

但我测试之后好像不是这样的,可能时jdk版本的问题吧,我的jdk版本时1.8.0_152

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

// 测试一,在遍历期间会将添加的元素加进去,但不会抛异常,与网上的说法有些不一致,网上说法时不会理会遍历期间添加的元素
Set set = hashMap.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
hashMap.put(10, 10);
System.out.println("此时 hashMap 长度为" + hashMap.size());
}
// 测试一结果:
//        1=1
//        此时 hashMap 长度为4
//        2=2
//        此时 hashMap 长度为4
//        3=3
//        此时 hashMap 长度为4
//        10=10
//        此时 hashMap 长度为4

// 测试二, 结果同一
Set<Integer> keySet = hashMap.keySet();
for (Integer index : keySet) {
System.out.println(hashMap.get(index));
hashMap.put(10, 10);
System.out.println("此时 hashMap 长度为" + hashMap.size());
}

// 测试三,
hashMap.forEach((o, o2) -> {
System.out.println(String.valueOf(o) + String.valueOf(o2));
hashMap.put(4, 4);
System.out.println("此时 hashMap 长度为" + hashMap.size());
});

// 测试三结果:
//        11
//        此时 hashMap 长度为4
//        22
//        此时 hashMap 长度为4
//        33
//        此时 hashMap 长度为4
//        44
//        此时 hashMap 长度为4

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java JDK