概述
什么是fail-fast?
简单的来说就是优先考虑出现异常的场景,当异常产生时,直接抛出异常,程序终止。
在jcl中的fail-fast?
fail-fast只要是体现在当我们在遍历集合元素的时候,经常会使用迭代器,但在迭代器遍历元素的过程中,如果集合的结构被改变的话,就会抛出异常ConcurrentModificationException,防止继续遍历。这就是所谓的快速失败机制。
这里要注意的这里说的结构被改变,是例如插入和删除这种操作,只是改变集合里的值的话并不会抛出异常。
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
list.add("C++");
list.add("Python");
list.add("PHP");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
if (str.equals("PHP")) {
list.remove(str);//因为移除了元素会抛异常
}
System.out.println(str);
}
}
这种机制最大的作用就在于多线程时保证多线程场景下不产生 “脏读”,一旦有线程在读取另一个线程想要更改就会直接抛出异常,可是直接抛出异常并不是我们想要的结果,应该采用线程安全的集合。
什么是fail-safe?
当我们对集合结构上做出改变的时候,fail-fast机制就会抛出异常。但是,对于采用fail-safe机制来说,就不会抛出异常。这是因为,==当集合的结构被改变的时候,fail-safe机制会在复制原集合的一份数据出来,然后在复制的那份数据遍历。==比如CopyOnWriteArrayList这个juc包下的线程安全集合类,就使用了fail-safe这个策略。
//CopyOnWriteArrayList 的 add方法
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);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
以这个集合的add为例,为什么CopyOnWriteArrayList不会抛ConcurrentModificationException异常就在于copy原来的array,再在copy数组上进行add操作,这样做就完全不会影响CopyOnWriteArrayList中的array了。当然像其他的如remove、clear等方法也使用相同的策略。
fail-safe的缺点
从上面的两个核心操作可以看出,fail-safe有一定的缺陷
1.复制时需要额外的空间和时间上的开销。
2.由于都是复制原来的数组,多线程时可能就不能保证遍历的是最新内容。
最后
以上就是兴奋乌龟为你收集整理的fail-fast策略以及fail-safe是什么?的全部内容,希望文章能够帮你解决fail-fast策略以及fail-safe是什么?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复