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 ...
随机推荐
- EJB 使用多个数据源问题
编辑 删除 如果在JBoss中同时使用俩个数据源就会发生如下异常: Transaction is not active: tx=TransactionImple < ac, BasicActio ...
- IntelliJ IDEA openfire 使用IntelliJ IDEA 部署OPENFIRE 服务端
用MyEclipse部署OF的步骤,网上有很多,可以自行google,这里要记录的是用据说最好用的JAVA编辑器IntelliJ IDEA来部署OF服务端.试了好多下,终于成功了,记录下. 直接上图吧 ...
- 一个PHP开发APP接口的视频教程
感觉php做接口方面的教程很少,无意中搜到了这个视频教程,希望能给一些人带来帮助http://www.imooc.com/learn/163
- ML-学习提纲1
http://www.sohu.com/a/130379077_468714 本文用一系列「思维导图」由浅入深的总结了「统计学」领域的基础知识,是对之前系列文章做的一次完整的梳理,也是我至今为止所有与 ...
- js join()和split()方法、reverse() 方法、sort()方法
############ join()和split()方法 join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 指定分隔符方法join("#&q ...
- vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示
vue :class 可以接收 字符串 数组 和 对象 对象里面的key值 根据true或false 显示不显示 https://cn.vuejs.org/v2/guide/class-and-sty ...
- iview table icon dorpdown html页面级别vue组件 #vuez#
iview table icon dorpdown html页面级别vue组件 <!DOCTYPE html> <html> <head> <meta cha ...
- iview分析
- Error:Failed to resolve: com.afollestad:material-dialogs:
http://www.chenruixuan.com/archives/1068.html 背景: 同事把Android项目直接考给了我...我在Android Studio上运行,然后提示: Err ...
- Perl 安装 JSON 包
$tar xvfz JSON.tar.gz $cd JSON $perl Makefile.PL $make $make install