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 ...
随机推荐
- [转]Qt 5.5 操作 Excel 的速度 效率问题
转自:http://blog.csdn.net/li494816491/article/details/50274305 1. QAxObject *_excelObject1 =newQAxObje ...
- NPM、nodeJS安装,grunt自动化构建工具学习总结
一:安装 npm是随nodeJs安装包一起安装的包管理工具,能解决NodeJS代码部署上的很多问题: 常见的使用场景有以下几种: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从N ...
- (译文)IOS block编程指南 3 概念总览
Conceptual Overview(概览) Block objects provide a way for you to create an ad hoc function body as an ...
- Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)
1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...
- Spring事务管理全面分析
Spring 事务属性分析什么是事物 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常 ...
- js join()和split()方法、reverse() 方法、sort()方法
############ join()和split()方法 join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 指定分隔符方法join("#&q ...
- 1+1/2+1/3+...+1/n为素数的证明
我们考虑不大于 n的最大的2 的幂 2^k. 令 有 其中 a/b是剩下的所有的项的和,由于乘以了最大的 2的幂,所以剩下的所有项的分母都是奇数,故而 b是奇数.如果 m是整数,那么就会导致等式右边的 ...
- json-server && axios
json-server && axios vue2.0项目实战(3)使用axios发送请求 https://www.cnblogs.com/zhouyangla/p/6753673.h ...
- 【转】解决WPF图片模糊最佳方法(绑定PixelWidth与PixelHeight)
解决WPF图片模糊最佳方法(绑定PixelWidth与PixelHeight) 转载自:http://www.360doc.com/content/13/1126/09/10504424_332211 ...
- mybaits2-Dao开发
项目结构: 1.创建project,导入相关依赖(前提).配置db.properties与mybaits-config #mysql驱动 db.driver=com.mysql.jdbc.Driver ...