- 浏览: 412737 次
- 性别:
- 来自: 济南
文章分类
最新评论
-
pmh905001:
写的很详尽,感谢!
解析jvm.dll和java.exe -
Bll:
插得真深啊,我的是(eclipse_j2ee_juno):F: ...
在eclipse里jsp编译后的java和class文件的位置 -
heming_way:
谢谢,对我很有用,解答了我对多值依赖的疑问
关于多值依赖--范式! -
JavaStudy2011:
java语言解析xml文件 -
vrussell:
Thanks man, it helps me a lot!
获得IEditorPart和IDocument
ConcurrentModificationException主要原因及处理方法
2007年04月18日 星期三 12:57
当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
把HashMap改成ConcurrentHashMap
也可以
先用HashMap进行操作!!
爆异常
java.util.HashMap$EntryIterator.next-----(积累----可以通过报异常 查看调用的什么方法!!)
(这里就是访问的HashMap内部类的EntryIterator)
看下源码
expectedModCount是为实现fail-fast实现的变量!
如果直接用HashMap中的方法删除的话 会导致两个变量不相等!!
看下ConcurrenthashMap中的Iterator实现
上面来自类 ConcurrentHashMap内部类
private abstract class HashIterator<E> implements Iterator<E>
可以看出
直接调用ConcurrentHashmap的removal方法!!
所以也没有研究的必要了
下面是 fail-fast的介绍
An iterator is considered fail-fast if it throws a ConcurrentModificationException under either of the following two conditions:
1.In multithreaded processing: if one thread is trying to modify a Collection while another thread is iterating over it.
2.In single-threaded or in multithreaded processing: if after the creation of the Iterator, the container is modified at any time by any method other than the Iterator's own remove or add methods.
Note in particular what is implied by the second condition: After we create a container's iterator, during a loop that iterates over the container we must only use the remove (and when applicable add) methods defined for the iterator and that we must NOT use the same methods defined for the container itself. To illustrate this point, suppose we declare and initialize a List in the following manner
List list = new ArrayList();
list.add("Peter");
list.add("Paul");
list.add("Mary");
Let's say we wish to iterate over this list. We'd need to declare a ListIterator as follows:
ListIterator iter = list.listIterator();
Having created this iterator, we could now set up a loop like:
while(iter1.hasNext()){
String str = iter1.next();
// do something with str
}
Because iter is fail-fast, we are not allowed to invoke List's add or remove methods inside the loop. Inside the loop, we are only allowed to use ListIterator's add and remove methods. This makes sense because it is the Iterator object that knows where it is in a List as the List is being scanned. The List object itself would have no idea of that.
The Iterators supported by all the work-horse container classes, such as ArrayList, LinkedList, TreeSet, and HashSet, are fail-fast. The Iterator type retrofitted to the older container class Vector is also fail-fast. For associative containers, such as HashMap and the older HashTable, the Iterator type for the Collections corresponding to either the keys or the values or the <key, value> pairs are fail-fast with respect to the container itself. That means that even if you are iterating over, say, just the keys of the container, any illegal concurrent modifications to the underlying container would be detected.
One final note regarding iterators versus enumerations: It is also possible to use an Enumeration object returned by the elements() method for iterating over the older container types such as Vector. However, Enumerations do not provide a fail-fast method. On the other hand, the more modern Iterator returned by a Vector's iterator() and listIterator() methods are fail-fast. Hence, iterators are recommended over enumerations for iterating over the elements of the older container types.
继承自AbstractList的List:LinkedList,ArrayList,Vector,Stack的Iterator都有这种属性
PriorityQueue的Iterator也有这种属性.
另外抽象类AbstractCollection 是集合的父母!
他的子类都实现了iterator()方法获得这个迭代集合!所以
他的子类1!
AbstractList, AbstractQueue, AbstractSet, ArrayDeque
以及他的子类都会有此特性!!
例如 TreeSet,
中种特性的实现方法是借助于一个modCount成员变量,记录structual modification的次数,在Iterator初始化时,让它的成员变量expectedModCount等于modCount,这样在Iterator做遍历时,如果发现 expectedModCount!= modCount就说明容器的内容发生了改变,抛出ConcurrentModificationException异常
2007年04月18日 星期三 12:57
当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.
把HashMap改成ConcurrentHashMap
也可以
1 public class MapIterator { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub begin(); } public static void begin() { ConcurrentHashMap hm2 =new ConcurrentHashMap(); HashMap<Integer,String> hm=new HashMap<Integer,String>(); char[] c=new char[1]; c[0]='a'; for(int i=0;i<10;i++) { c[0]+=i; hm.put(new Integer(i),new String(c)); } Set s=hm.entrySet(); Iterator i=s.iterator(); Map.Entry<Integer,String> me; while(i.hasNext()) { me=(Map.Entry<Integer,String>)i.next(); //System.out.println(me.getKey()); System.out.println(hm.size()); hm.remove(me.getKey()); } System.out.println(hm.size()); } }
先用HashMap进行操作!!
爆异常
java.util.HashMap$EntryIterator.next-----(积累----可以通过报异常 查看调用的什么方法!!)
(这里就是访问的HashMap内部类的EntryIterator)
看下源码
Form HashIterator public void remove() { if (current == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); Object k = current.key; current = null; HashMap.this.removeEntryForKey(k); expectedModCount = modCount; }
expectedModCount是为实现fail-fast实现的变量!
如果直接用HashMap中的方法删除的话 会导致两个变量不相等!!
看下ConcurrenthashMap中的Iterator实现
public void remove() { if (lastReturned == null) throw new IllegalStateException(); ConcurrentHashMap.this.remove(lastReturned.key); lastReturned = null; }
上面来自类 ConcurrentHashMap内部类
private abstract class HashIterator<E> implements Iterator<E>
可以看出
直接调用ConcurrentHashmap的removal方法!!
所以也没有研究的必要了
下面是 fail-fast的介绍
An iterator is considered fail-fast if it throws a ConcurrentModificationException under either of the following two conditions:
1.In multithreaded processing: if one thread is trying to modify a Collection while another thread is iterating over it.
2.In single-threaded or in multithreaded processing: if after the creation of the Iterator, the container is modified at any time by any method other than the Iterator's own remove or add methods.
Note in particular what is implied by the second condition: After we create a container's iterator, during a loop that iterates over the container we must only use the remove (and when applicable add) methods defined for the iterator and that we must NOT use the same methods defined for the container itself. To illustrate this point, suppose we declare and initialize a List in the following manner
List list = new ArrayList();
list.add("Peter");
list.add("Paul");
list.add("Mary");
Let's say we wish to iterate over this list. We'd need to declare a ListIterator as follows:
ListIterator iter = list.listIterator();
Having created this iterator, we could now set up a loop like:
while(iter1.hasNext()){
String str = iter1.next();
// do something with str
}
Because iter is fail-fast, we are not allowed to invoke List's add or remove methods inside the loop. Inside the loop, we are only allowed to use ListIterator's add and remove methods. This makes sense because it is the Iterator object that knows where it is in a List as the List is being scanned. The List object itself would have no idea of that.
The Iterators supported by all the work-horse container classes, such as ArrayList, LinkedList, TreeSet, and HashSet, are fail-fast. The Iterator type retrofitted to the older container class Vector is also fail-fast. For associative containers, such as HashMap and the older HashTable, the Iterator type for the Collections corresponding to either the keys or the values or the <key, value> pairs are fail-fast with respect to the container itself. That means that even if you are iterating over, say, just the keys of the container, any illegal concurrent modifications to the underlying container would be detected.
One final note regarding iterators versus enumerations: It is also possible to use an Enumeration object returned by the elements() method for iterating over the older container types such as Vector. However, Enumerations do not provide a fail-fast method. On the other hand, the more modern Iterator returned by a Vector's iterator() and listIterator() methods are fail-fast. Hence, iterators are recommended over enumerations for iterating over the elements of the older container types.
继承自AbstractList的List:LinkedList,ArrayList,Vector,Stack的Iterator都有这种属性
PriorityQueue的Iterator也有这种属性.
另外抽象类AbstractCollection 是集合的父母!
他的子类都实现了iterator()方法获得这个迭代集合!所以
他的子类1!
AbstractList, AbstractQueue, AbstractSet, ArrayDeque
以及他的子类都会有此特性!!
例如 TreeSet,
中种特性的实现方法是借助于一个modCount成员变量,记录structual modification的次数,在Iterator初始化时,让它的成员变量expectedModCount等于modCount,这样在Iterator做遍历时,如果发现 expectedModCount!= modCount就说明容器的内容发生了改变,抛出ConcurrentModificationException异常
发表评论
-
throw 和throws碰到runtimeException
2010-09-02 21:36 37551.throws 用于抛出方法层次的异常, 并且直接由些方法 ... -
Hashtable中的数据结构
2010-08-23 11:38 1095看下Hashtable中的put 方法 public sy ... -
关于StringBuffer的拓展
2010-08-20 16:02 861先访照StringBuffer的append写个类 pub ... -
转帖 精解Classloader
2010-08-18 20:11 938当JVM(Java虚拟机)启动时,会形成由三个类加载器组成的初 ... -
jvm解析多线程
2010-08-18 16:36 1227先看jvm对多线程关于对 ... -
Classloader getResourceAsStream深入
2010-08-17 17:37 1231先写个简单的类 public class Helper { ... -
ClassLoader的基础详解
2010-08-12 13:28 2364java应用环境中不同的class分别由不同的ClassLoa ... -
关于Classloader的总结!loadClass的分析和加载细节的分析
2010-08-12 11:13 8041package com.test.one; import ... -
unicode下的String
2010-07-30 19:34 1066先看一个代码 String o="1" ... -
集合总结
2010-05-31 20:50 985-集合接口:6个接口(短虚线表示),表示不同集合类型,是集 ... -
自己写的根据unix纪元法 得到时间
2010-05-29 09:46 1978在著名的unix系统中,使用了一种简洁高效的时间表示方法,即: ... -
进阶Enum
2010-05-29 09:42 866先说下enum这个类 private enum Colo ... -
中文转化为unicode
2010-05-28 16:37 1676原文地址: http://www.cnitblog.com/n ... -
构造函数 方法 void 关键字
2010-05-25 22:05 1591public final class Void extends ... -
(转)ConcurrentHashMap实现细节
2010-05-25 16:20 1089原文 http://www.iteye.com/topic/3 ... -
Checked Exception与Runtime Exception 的区别(转)
2010-04-30 11:03 1151原文:http://www.jspcn.net/h ... -
数组分配的字节码分析
2010-04-25 21:29 1615int [][]a=new int[3][5]; Sys ...
相关推荐
NULL 博文链接:https://chenlinbo.iteye.com/blog/832335
Java中的For each实际上使用的是iterator进行处理的。而iterator是不允许集合在...而我在for each时,从集合中删除了一个元素,这导致了iterator抛出了ConcurrentModificationException,下面来看看到底怎么回事。
java.util.ConcurrentModificationException 异常问题详解1
只读迭代:由于写时复制的机制,CopyOnWriteArraySet 的迭代器是只读的,即迭代过程中不会抛出 ConcurrentModificationException 异常。但是,迭代器获得的数据可能不包含最新的修改。 较高的内存占用:由于每次...
Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。
迭代时被修改抛出ConcurrentModificationException异常 迭代时集合被修改不抛出异常 使用原集合遍历集合元素 使用原集合的副本遍历集合元素 迭代器不要求额外的内存 迭代器需要额外的内存克隆集合对象 示例:...
Iterator遍历中 ConcurrentModificationException异常
java集合 线程不安全的集合 HashMap的特点 HashMap的长度(容量)为什么要设计成2的幂? HashTable的特点 TreeMap ArrayList的特点 Vector的特点 LinkedList的特点 Set ConcurrentModificationException异常 线程...
在使用iterator.hasNext()操作迭代器的时候,如果此时迭代的对象发生改变,比如插入了新数据,或者有数据被删除。 则使用会报以下异常: Java.util.ConcurrentModificationException at java.util.HashMap$...
iterator和listIterator方法是快速失败的 :如果列表在任何时间从结构上修改创建迭代器之后,以任何方式,除了通过迭代器自身的remove或add方法,迭代器都将抛出ConcurrentModificationException 。 因此,在并发的...
主要介绍了出现java.util.ConcurrentModificationException 问题及解决办法的相关资料,需要的朋友可以参考下
Java集合类中,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不确定的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection ...
那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。 fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-...
(结构修改是添加或删除一个或多个元素的任何操作,或明确调整后台数组的大小;仅设置元素的值不是结构修改。)这通常是通过在一些自然地封装了列表。 如果没有这样的对象存在,列表应该使用Collections....
java8集合源码sbt run 锌抛: [info] running example.MainClass [info] compiling 1 Java source to C:\Users\Chikei\AppData\Local\Temp\zincClasses336102448129471145 ... [error] ## Exception when compiling ...
今天小编就为大家分享一篇关于Java源码解析ArrayList及ConcurrentModificationException,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
axis1.4补丁包,解决jdk1.8高并发报ConcurrentModificationException问题,该jar包重新编译jar包的一个class文件,线上环境通过
Spring数据mongodb测试 在Collections.synchronizedList或Collections.synchronizedSet上测试spring数据mongodb ConcurrentModificationException
axis1.4 spring3.0 集成 实现 web service 服务端, axis1.4 客户端认证,授权,访问日志记录,集成spring 解决 PHP 调用web service 无法认证,和解析soap 模板