博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面试官:说说快速失败和安全失败是什么
阅读量:2059 次
发布时间:2019-04-29

本文共 1826 字,大约阅读时间需要 6 分钟。

什么是快速失败(fail-fast)和安全失败(fail-safe)?它们又和什么内容有关系。以上两点就是这篇文章的内容,废话不多话,正文请慢用。

我们都接触 HashMap、ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的;而 java.util.concurrent 包下的类都是安全失败,比如:ConcurrentHashMap。

1. 快速失败(fail-fast)

在使用迭代器对集合对象进行遍历的时候,如果 A 线程正在对集合进行遍历,此时 B 线程对集合进行修改(增加、删除、修改),或者 A 线程在遍历过程中对集合进行修改,都会导致 A 线程抛出 ConcurrentModificationException 异常。

具体效果我们看下代码:

HashMap hashMap = new HashMap();        hashMap.put("不只Java-1", 1);        hashMap.put("不只Java-2", 2);        hashMap.put("不只Java-3", 3);        Set set = hashMap.entrySet();        Iterator iterator = set.iterator();        while (iterator.hasNext()) {            System.out.println(iterator.next());            hashMap.put("下次循环会抛异常", 4);            System.out.println("此时 hashMap 长度为" + hashMap.size());        }

执行后的效果如下图:

为什么在用迭代器遍历时,修改集合就会抛异常时?

原因是迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。

每当迭代器使用 hashNext()/next() 遍历下一个元素之前,都会检测 modCount 变量是否为 expectedModCount 值,是的话就返回遍历;否则抛出异常,终止遍历。

2. 安全失败(fail-safe)

明白了什么是快速失败之后,安全失败也是非常好理解的。

采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,故不会抛 ConcurrentModificationException 异常

我们上代码看下是不是这样

ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();        concurrentHashMap.put("不只Java-1", 1);        concurrentHashMap.put("不只Java-2", 2);        concurrentHashMap.put("不只Java-3", 3);        Set set = concurrentHashMap.entrySet();        Iterator iterator = set.iterator();        while (iterator.hasNext()) {            System.out.println(iterator.next());            concurrentHashMap.put("下次循环正常执行", 4);        }        System.out.println("程序结束");

运行效果如下,的确不会抛异常,程序正常执行。

最后说明一下,快速失败和安全失败是对迭代器而言的。并发环境下建议使用 java.util.concurrent 包下的容器类,除非没有修改操作。

参考文章:

PS:本文原创发布于微信公众号「不只Java」,后台回复「Java」,送你 13 本 Java 经典电子书。公众号专注分享 Java 干货、读书笔记、成长思考

转载地址:http://hialf.baihongyu.com/

你可能感兴趣的文章
Kubernetes 使用 ceph-csi 消费 RBD 作为持久化存储
查看>>
Ceph万字总结|如何改善存储性能以及提升存储稳定性
查看>>
啥?Grafana 还能为日志添加告警?
查看>>
尚硅谷新版k8s视频教程
查看>>
CentOS: 永远有多远就离它多远
查看>>
重新夺回对 /etc/resolv.conf 的控制权
查看>>
突破 DockerHub 限制,全镜像加速服务
查看>>
使用 Sealos + Longhorn 部署 KubeSphere v3.0.0
查看>>
10小时,这回一次搞定 Kafka 源码!
查看>>
运维总监怒怼开发:你真的需要K8S吗?
查看>>
Prometheus hang 住问题定位解决
查看>>
别看 DNS 污染闹得欢,现在我用 CoreDNS 将它拉清单
查看>>
百度为什么掉队了
查看>>
Containerd 中的 Snapshot 到底是个什么鬼?
查看>>
Dockerd 资源泄露怎么办
查看>>
高性能 Nginx HTTPS 调优 - 如何为 HTTPS 提速 30%
查看>>
在 Kubernetes 中部署高可用 Harbor 镜像仓库
查看>>
容器网络一直在颤抖,罪魁祸首竟然是 ipvs 定时器
查看>>
阿里宣布拆中台,首当其冲就是优化数据中台架构?
查看>>
Cilium 源码解析:Node 之间的健康探测(health probe)机制
查看>>