170118、快速失败Vs安全失败(Java迭代器附示例)
简介:
当错误发生时,如果系统立即关闭,即是快速失败,系统不会继续运行。运行中发生错误,它会立即停止操作,错误也会立即暴露。而安全失败系统在错误发生时不会停止运行。它们隐蔽错误,继续运行,而不会暴露错误。这两种模式,孰优孰优,是系统设计中常讨论的话题,在此,我们只讨论java中的快速失败和安全失败迭代器。
Java快速失败与安全失败迭代器 :
java迭代器提供了遍历集合对象的功能,集合返回的迭代器有快速失败型的也有安全失败型的,快速失败迭代器在迭代时如果集合类被修改,立即抛出ConcurrentModificationException异常,而安全失败迭代器不会抛出异常,因为它是在集合类的克隆对象上操作的。我们来看看快速失败和 安全失败迭代器的具体细节。
java快速失败迭代器 :
大多数集合类返回的快速失败迭代器在遍历时不允许结构性修改(结构性修改指添加,删除和更新一个元素) 当遍历的同时被结构性修改,就会抛出ConcurrentModificationException异常,而当集合是被迭代器自带的方法(如remove())修改时,不会抛出异常。
快速失败迭代器运行原理:
所有的集合类都维护着一个对象数组(Object[]),用来存储元素, 快速失败迭代器直接从数组中获取元素,在迭代过程中,总是假定该内部数组不会被修改。为了判断这个集合是否被修改,它们使用名为modCount的内部标识,当集合被修改,该标识也会更新。迭代器每次调用next()方法,都会检查modCount,如果发现modCount被更新,就会抛出ConcurrentModificationException异常。
ArrayList,Vector,HashMap等集合返回的迭代器都是快速失败类型的。
import java.util.ArrayList;
import java.util.Iterator;
public class FailFastIteratorExample
{
public static void main(String[] args)
{
//Creating an ArrayList of integers
ArrayList<Integer> list = new ArrayList<Integer>();
//Adding elements to list
list.add(1452);
list.add(6854);
list.add(8741);
list.add(6542);
list.add(3845);
//Getting an Iterator from list
Iterator<Integer> it = list.iterator();
while (it.hasNext())
{
Integer integer = (Integer) it.next();
list.add(8457); //This will throw ConcurrentModificationException
}
}
}
Output :
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at pack1.MainClass.main(MainClass.java:32)
Java安全失败迭代器 :
安全失败迭代器在迭代中被修改,不会抛出任何异常,因为它是在集合的克隆对象迭代的,所以任何对原集合对象的结构性修改都会被迭代器忽略,但是这类迭代器有一些缺点,其一是它不能保证你迭代时获取的是最新数据,因为迭代器创建之后对集合的任何修改都不会在该迭代器中更新,还有一个缺点就是创建克隆对象在时间和内存上都会增加一些负担。
ConcurrentHashMap返回的迭代器是安全失败迭代器:
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
public class FailSafeIteratorExample
{
public static void main(String[] args)
{
//Creating a ConcurrentHashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
//Adding elements to map
map.put("ONE", 1);
map.put("TWO", 2);
map.put("THREE", 3);
map.put("FOUR", 4);
//Getting an Iterator from map
Iterator<String> it = map.keySet().iterator();
while (it.hasNext())
{
String key = (String) it.next();
System.out.println(key+" : "+map.get(key));
map.put("FIVE", 5); //This will not be reflected in the Iterator
}
}
}
Output :
TWO : 2
FOUR : 4
ONE : 1
THREE : 3
| 快速失败迭代器 | 安全失败迭代器 |
| 在迭代时不允许修改集合 | 在迭代时允许修改集合 |
| 迭代时被修改抛出ConcurrentModificationException异常 | 迭代时集合被修改不抛出异常 |
| 使用原集合遍历集合元素 | 使用原集合的副本遍历集合元素 |
| 迭代器不要求额外的内存 | 迭代器需要额外的内存克隆集合对象 |
| 示例:ArrayList, Vector, HashMap | 示例:ConcurrentHashMap |
译者语:
总体而言是一篇好文章,就是有一个地方和javadoc有出入,即“大多数集合类返回的快速失败迭代器在遍历时不允许结构性修改(结构性修改指添加,删除和更新集合中一个元素)”这一句,而javadoc中对此的解释是“结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。” 以javadoc中的为准。
此文转载...
170118、快速失败Vs安全失败(Java迭代器附示例)的更多相关文章
- Java笔记-快速失败and安全失败
参考资料:http://blog.csdn.net/chenssy/article/details/38151189 快速失败 fail-fast 安全失败 fail-safe java.util包下 ...
- Java 快速失败( fail-fast ) 安全失败( fail-safe )
原文:http://www.cnblogs.com/ygj0930/p/6543350.html 快速失败( fail-fast ):当你在迭代一个集合的时候,如果有另一个线程正在修改你正在访问的那个 ...
- 【1】ConcurrentModificationException 异常解析和快速失败,安全失败
目录 一.引起异常的代码 二.foreach原理 三.从ArrayList源码找原因 四.单线程解决方案 五.在多线程环境下的解决方法 一.引起异常的代码 以下三种的遍历集合对象时候,执行集合的rem ...
- 快速失败and安全失败
快速失败: 举个栗子: public static void main(String[] args) { ArrayList<String> list=new ArrayList<& ...
- Java 迭代器综述
一.摘要 迭代器模式是与集合共生共死的.一般来说.我们仅仅要实现一个容器,就须要同一时候提供这个容器的迭代器.使用迭代器的优点是:封装容器的内部实现细节,对于不同的集合,能够提供统一的遍历方式,简化c ...
- Java迭代器[转]
迭代器是一种模式,它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的.只要拿到这个对象,使用迭代器就可以遍历这个对象的内部. 1.Iterator ...
- 【Java学习】Java迭代器
迭代器是一种模式,它可以使得对于序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的.只要拿到这个对象,使用迭代器就可以遍历这个对象的内部. 1.Iterator ...
- [转载]Java迭代器(iterator详解以及和for循环的区别)
Java迭代器(iterator详解以及和for循环的区别) 觉得有用的话,欢迎一起讨论相互学习~[Follow] 转载自 https://blog.csdn.net/Jae_Wang/article ...
- 黑马----JAVA迭代器详解
JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...
随机推荐
- .Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)
过去几年都在忙着找项目,赶项目,没有时间好好整理深究自己在工作中学到的东西.现在好了,趁着找工作的这段空余时间,正好可以总结和再继续夯实自己的.Net, C#基本功.在05年的时候,Scott Han ...
- Mac 上的一些骚操作和技巧
0.自定义mac touch bar 上的图标 系统偏好设置-键盘-自定义control strip.. 接下来就精彩了:先用手指按住你touch bar 的siri,然后移到最左边的删除图标,将它移 ...
- Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast)
Atitit.软件开发的最终的设计 dsl化,ast化(建立ast, 解析执行ast) 1. 使用js,html 撰写dsl1 1.1. 架构图1 1.2. html2 1.3. Js2 1.4. C ...
- 品茗论道说广播(Broadcast内部机制讲解)(上)
1 概述 我们在编写Android程序时,常常会用到广播(Broadcast)机制.从易用性的角度来说,使用广播是非常简单的.不过,这个不是本文关心的重点,我们希望探索得再深入一点儿.我想,许多人也不 ...
- C++语言基础(25)-C++格式化输出
一.使用控制符控制输出格式 #include <iostream> #include <iomanip>//不要忘记包含此头文件 using namespace std; in ...
- redis源码学习_整数集合
redis里面的整数集合保存的都是整数,有int_16.int_32和int_64这3种类型,和C++中的set容器差不多. 同时具备如下特点: 1.set里面的数不重复,均为唯一. 2.set里面的 ...
- python学习之urllib.parse.unquote()
urllib.parse.unquote(string,encoding ='utf-8',errors ='replace') 用同一个字符换成%xx转义.相当于JS中的urldecode(),对u ...
- Mac上Nginx-增加对HLS的支持
Mac上Nginx-增加对HLS的支持 我们在Mac上搭建直播服务器Nginx说了如何在Mac搭建视频直播服务器Nginx,对RTMP推流和RTMP拉流的支持.接下来说说如何增加对HLS的支持. 在N ...
- java实现word转pdf文件(高效不失真)
import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import org.aspectj ...
- DMA—直接存储区访问
本章参考资料:< STM32F4xx 中文参考手册> DMA 控制器章节.学习本章时,配合< STM32F4xx 中文参考手册> DMA 控制器章节一起阅读,效果会更佳,特别是 ...