博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java fail-fast 与 fail-safe 机制对比
阅读量:4465 次
发布时间:2019-06-08

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

关于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
list = new CopyOnWriteArrayList
(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
map = new ConcurrentHashMap
(); 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
implements List
, 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
iterator() { return new COWIterator
(getArray(), 0); //直接用原来的数据数组 } final Object[] getArray() { return array; } static final class COWIterator
implements ListIterator
{ /** 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.cnblogs.com/simpleito/p/10901899.html

你可能感兴趣的文章
【BZOJ3926】【ZJOI2015】—诸神眷顾的幻想乡(广义后缀自动机)
查看>>
测者的测试技术手册:自动的自动化框架EvoSuite集成Cobertura得到可视化的代码覆盖报告...
查看>>
"Hello World!" for the NetBeans IDE
查看>>
AlertDialog弹出退出对话框和图片对话框
查看>>
ASP.NET页面间数据传递的方法
查看>>
函数—参数会变吗
查看>>
Windows 10 v9926 初测
查看>>
Perl单URL爬虫
查看>>
Memcached
查看>>
codeforces 25D
查看>>
多校 2009 2
查看>>
uva 305 Joseph
查看>>
移植rtmpdump(librtmp)到android
查看>>
类查找android中跨项目的数据库操作ContentProvider的使用
查看>>
WCF也可以做聊天程序
查看>>
HDU 4497 素数筛,合数分解
查看>>
一文看懂python主要应用领域或应用场景
查看>>
DC学习(8)综合与优化
查看>>
Python中关于字符串的各种方法
查看>>
SSD S.M.A.R.T
查看>>