@ghimi
2018-05-14T09:03:51.000000Z
字数 2246
阅读 897
java
迭代器
当错误发生时,如果系统立即关闭,即是快速失败,系统不会继续运行。运行中发生错误,它会立即停止操作,错误也会立即暴露。而安全失败系统在错误发生时不会停止运行。它们隐蔽错误,继续运行,而不会暴露错误。这两种模式,孰优孰优,是系统设计中常讨论的话题,在此,我们只讨论java中的快速失败迭代器和安全失败迭代器。
java迭代器提供了遍历集合对象的功能,集合返回的迭代器有快速失败型的也有安全失败型的,快速失败迭代器在迭代时如果集合类被修改,立即抛出ConcurrentModificationException异常,而安全失败迭代器不会抛出异常,因为它是在集合类的克隆对象上操作的。我们来看看快速失败和 安全失败迭代器的具体细节。
大多数集合类返回的快速失败迭代器在遍历时不允许结构性修改(结构性修改指添加,删除和更新一个元素)当遍历的同时被结构性修改,就会抛出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)
安全失败迭代器在迭代中被修改,不会抛出任何异常,因为它是在集合的克隆对象迭代的,所以任何对原集合对象的结构性修改都会被迭代器忽略,但是这类迭代器有一些缺点,其一是它不能保证你迭代时获取的是最新数据,因为迭代器创建之后对集合的任何修改都不会在该迭代器中更新,还有一个缺点就是创建克隆对象在时间和内存上都会增加一些负担。
安全失败迭代器类型的例子有: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 int the Iterator
}
}
}
Output :
TWO : 2
FOUR : 4
ONE : 1
THREE : 3