Java fail-fast 与 fail-safe 机制对比
关于fail-fast参考这篇文章:
从 modCount 看 java集合 fail-fast 机制
一、fail-safe概述以及与fail-fast区别
首先 fail-safe 并不属于JavaSE规范术语,只是用以说明 fail-fast 与 non-fail fast 的区别。
这种机制的迭代器允许在迭代时修改集合,且不会抛出任何异常。不同的类实现方式有所不同,通常是因为"迭代"与"修改操作"使用的不是同一个数据数组,比如CopyOnWirteArrayList在修改时会创建一个原数组副本(只是新建一个数组,浅克隆)在新数组上修改后再将指针指向新数组,而此时迭代器中的指针仍指向原数组。
因此这种迭代器无法保证在迭代时获取的是最新数据,比如:(1)CopyOnWriteArrayList在迭代过程中的数据更新无法在迭代中表现出来。(2)ConcurrentHashMap的弱一致性迭代器。
注:弱一致性迭代器可能会(但不保证)将迭代过程中的修改表现出来。
ConcurrentHashMap迭代器官方注释:
The iterators returned by ConcurrentHashMap is weakly consistent. This means that this iterator can tolerate concurrent modification, traverses elements as they existed when iterator was constructed and may (but not guaranteed to) reflect modifications to the collection after the construction of the iterator.
二、示例
2.1 CopyOnWriteArrayList示例
public static void main(String args[])
{
CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<Integer>(new Integer[] { 1, 3, 5, 8 });
Iterator itr = list.iterator();
while (itr.hasNext()) {
Integer no = (Integer)itr.next();
System.out.println(no);
if (no == 8)
list.add(14); //不会打印
}
}
输出:
1
3
5
8
2.2 ConcurrentHashMap示例
public static void main(String[] args)
{
// Creating a ConcurrentHashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
map.put("ONE", 1);
map.put("TWO", 2);
map.put("THREE", 3);
map.put("FOUR", 4);
// Getting an Iterator from map
Iterator it = map.keySet().iterator();
while (it.hasNext()) {
String key = (String)it.next();
System.out.println(key + " : " + map.get(key));
//一般会打印
//但若改成("FIVE",5)则基本不会打印,可能与弱一致性迭代器内部逻辑有关
map.put("SEVEN", 7);
}
}
三、实现原理解析
3.1 CopyOnWriteArrayList对fail-safe实现
CopyOnWriteArrayList 在修改时会创建一个原数组副本(只是新建一个数组,浅克隆)在新数组上修改后再将集合的数组指针指向新数组对象,而此时迭代器中的指针仍指向原数组对象。迭代过程中的修改,不会反映到迭代上。
源码解析:
public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
//!只放关键代码
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array; //存放数据数组
//添加方法
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); //浅克隆原数组并长度+1
newElements[len] = e; //在新数组上进行添加
setArray(newElements); //将数组指针指向新数组
return true;
} finally {
lock.unlock();
}
}
//迭代器方法
public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0); //直接用原来的数据数组
}
final Object[] getArray() {
return array;
}
static final class COWIterator<E> implements ListIterator<E> {
/** Snapshot of the array */
private final Object[] snapshot;
/** Index of element to be returned by subsequent call to next. */
private int cursor; //始终指向下一个元素
private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements; //将引用snapshot指向传入的原数组
}
//…
public E next() {
if (! hasNext())
throw new NoSuchElementException();
return (E) snapshot[cursor++];
}
}
}
3.2 ConcurrentHashMap对fail-safe实现
ConcurrentHashMap并非通过拷贝数组修改来实现的fail-safe…
//TODO:
参考:
https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/
Java fail-fast 与 fail-safe 机制对比的更多相关文章
- Fail Fast and Fail Safe Iterators in Java
https://www.geeksforgeeks.org/fail-fast-fail-safe-iterators-java/ Fail Fast and Fail Safe Iterators ...
- fail fast和fail safe策略
优先考虑出现异常的场景,当程序出现异常的时候,直接抛出异常,随后程序终止 import java.util.ArrayList; import java.util.Collections; impor ...
- 快速失败(fail—fast)和 安全失败(fail—safe)
快速失败(fail-fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的结构进行了修改(增加.删除),则会抛出Concurrent Modification Exception. 原理 ...
- 【问题】Could not locate PropertySource and the fail fast property is set, failing
这是我遇到的问题 Could not locate PropertySource and the fail fast property is set, failing springcloud的其他服务 ...
- FastDFS :java.lang.Exception: getStoreStorage fail, errno code: 28
FastDFS 服务正常,突然报错:java.lang.Exception: getStoreStorage fail, errno code: 28 答:错误代码28表示 No space left ...
- 转 Java虚拟机5:Java垃圾回收(GC)机制详解
转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...
- java 多线程总结篇4——锁机制
在开发Java多线程应用程序中,各个线程之间由于要共享资源,必须用到锁机制.Java提供了多种多线程锁机制的实现方式,常见的有synchronized.ReentrantLock.Semaphore. ...
- Java并发编程:Concurrent锁机制解析
Java并发编程:Concurrent锁机制解析 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: # ...
- Apache与Nginx对客户端请求的处理机制对比
Apache与Nginx对客户端请求的处理机制对比 模块 大致为四个模块,核心模块.HTTP模块.邮件模块,以及第三方模块 核心模块主要包含两类功能的支持,一类是主体功能,包括进程管理,权限管理,错误 ...
- 【转】Java之 内存区域和GC机制
转自:Leo Chin 目录 Java垃圾回收概况 Java内存区域 Java对象的访问方式 Java内存分配机制 Java GC机制 垃圾收集器 Java垃圾回收概况 Java GC(Garbage ...
随机推荐
- NPM、nodeJS安装,grunt自动化构建工具学习总结
一:安装 npm是随nodeJs安装包一起安装的包管理工具,能解决NodeJS代码部署上的很多问题: 常见的使用场景有以下几种: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从N ...
- Elasticsearch 插入地理索引文档一直为空
今天在获取插入索引数据的时候,一直提示插入不成功,尝试了很多方法,原来是因为在插入的时候应该先 插入Latitude后插入longitude修改后的代码如下 public boolean insert ...
- 30行代码消费腾讯人工智能开放平台提供的自然语言处理API
腾讯人工智能AI开放平台上提供了很多免费的人工智能API,开发人员只需要一个QQ号就可以登录进去使用. 腾讯人工智能AI开放平台的地址:https://ai.qq.com/ 里面的好东西很多,以自然语 ...
- Python3简明教程(一)—— 开始Python之旅
第一个Python程序 作为我们第一个Python程序——打印"Hello World!". 在终端输入Python3进入交互界面: 输入print("Hello W ...
- uva10570 Meeting with Aliens
先证明把每次i放到i位置最后次数最少:感觉,可以,用归纳法? //在序列后再加一个相同的序列,就可以模拟用各个数字开头的情况了每个位置不对的只需要换一次54123 ,5固定->41235变成12 ...
- vs2008控件查看器
使用 OLE/COM 对象查看器 通过读取控件的类型库,OLE/COM 对象查看器使您得以查看控件的接口. 使用 OLE/COM 对象查看器 单击“工具”菜单上的“OLE/COM 对象查看器”或在命令 ...
- 枚举 || CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution
给出N*M矩阵,对于该矩阵有两种操作: 1.交换两列,对于整个矩阵只能操作一次 2.每行交换两个数. 交换后是否可以使每行都递增. *解法:N与M均为20,直接枚举所有可能的交换结果,进行判断 每次枚 ...
- Visual Odometry
http://www.cvlibs.net/datasets/kitti/eval_odometry.php
- Needleman_Wunsch
Needleman_Wunsch算法思路: 1.建立二维数组 2.建立评分模式 load1:向右:-2 load2:向下:-2 load3:对角线:依据是否配得到 匹配:+1 不匹配:-1 3.双层循 ...
- UIWebView与js那些事
UIWebView是IOS SDK中渲染网面的控件,在显示网页的时候,我们可以hack网页然后显示想显示的内容.其中就要用到javascript的知识,而UIWebView与javascript交互的 ...