ConcurrentModificationException 异常:并发修改异常,当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。一个线程对collection集合迭代,另一个线程对Collection进行修改的时候, 就会出现上面的异常.

下面看一下代码:

package cn.itcast.p4.list.demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; public class ListIteratorException { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
List<String>list = new ArrayList<String>();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
Iterator it = list.iterator();
while(it.hasNext()){
String s = (String) it.next();
if(s.equals("abc2")){
list.remove(s);
}else{
System.out.println(s);
}
}
System.out.println(list);
} }

运行结果:

abc1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
    at java.util.AbstractList$Itr.next(AbstractList.java:343)
    at cn.itcast.p4.list.demo.ListIteratorException.main(ListIteratorException.java:22)

看list.iterator()方法的源码:

    public Iterator<E> iterator() {
return new Itr();
}
  private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0; /**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1; /**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
通过看API AbstractList.class 发现该类里面有一个成员变量: protected transient int modCount = 0;
是不可被序列化的变量,当对集合进行add,remove,removeRange,addAll等修改动作的时候,没操作一次,modCount加1。
用来记录对集合修改的次数。

*/
int expectedModCount = modCount;//上面因为翻译过来,为迭代器的expectedModCount值和List集合中的modCount 初始值一致 public boolean hasNext() {
return cursor != size();
} public E next() {
checkForComodification();//每调用一次next方法,都要通过此方法检测expectedModCount(迭代对象的后)
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
} public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification(); try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
//用来检测现在的List中的modCount与创建迭代器的时候初始expectedModCount值是否想相等,不相等,返回异常ConcurrentModificationException
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

可能大家对modCount还不明白,再看下AbstractList.Class里面的源代码:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

    protected transient int modCount = 0;
class SubList<E> extends AbstractList<E> { 。。。。。。。。省略很多代码。。。。。。。。。。。。。
public void add(int index, E element) {
if (index<0 || index>size)
throw new IndexOutOfBoundsException();
checkForComodification();
l.add(index+offset, element);
expectedModCount = l.modCount;
size++;
modCount++;
} public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
expectedModCount = l.modCount;
size--;
modCount++;
return result;
} }
}

分析上面的源代码:

   通过看API AbstractList.class 发现该类里面有一个成员变量: protected transient int modCount = 0, 是不可被序列化的变量,当对集合
进行add,remove,removeRange,addAll等修改动作的时候,每修改一次,modCount加1。用来记录对集合修改的次数
private class Itr 类里面有一个成员变量expectedModCount,初始值和List中的modCount一样,只要在迭代的过程中线程没有对List集合进行
上面的修改动作,modCount值就不会变。那么expectedModCount=modCount条件始终成立,checkForComodification检测集合是否被修改的
方法里面的if判断不成立,不会抛出异常。
但是在我们的程序中,执行到list.remove(s);时候,一个线程对集合进行it.next()遍历,一个线程对集合进行remove动作,这样当删除"abc2"对象后,
list对象的成员变量modCount的值+1,但是迭代对象Itr 里面的expectedModCount不变,所以两个值不相等,等再次调用next()方法后,
调用checkForComodification方法,if条件成立,这样就抛出了异常。
 

java集合--java.util.ConcurrentModificationException异常的更多相关文章

  1. java.util.ConcurrentModificationException 异常问题详解

    环境:JDK 1.8.0_111 在Java开发过程中,使用iterator遍历集合的同时对集合进行修改就会出现java.util.ConcurrentModificationException异常, ...

  2. java.util.ConcurrentModificationException异常原因及解决方法

    在java语言中,ArrayList是一个很常用的类,在编程中经常要对ArrayList进行删除操作,在使用remove方法对ArrayList进行删除操作时,报java.util.Concurren ...

  3. java.util.ConcurrentModificationException异常分析

    Java在操作ArrayList.HashMap.TreeMap等容器类时,遇到了java.util.ConcurrentModificationException异常.以ArrayList为例,如下 ...

  4. Java 迭代器删除元素ConcurrentModificationException异常。

    Java是不支持容器类在使用迭代器迭代过程中,使用如 list.remove(obj)方法删除元素.否则会抛出ava.util.ConcurrentModificationException异常.应该 ...

  5. Java处理java.util.ConcurrentModificationException异常

    代码: public static void reduce(HashMap<String, Integer> hashMap, final Integer count) { Iterato ...

  6. java.util.ConcurrentModificationException异常排查

      java.util.ConcurrentModificationException对于这个异常我们一般会认为是在遍历list的时候对这个list做了add,remove等修改操作造成的,最近在线上 ...

  7. java.util.ConcurrentModificationException 异常解决的方法及原理

    近期在修程序的bug,发现后台抛出下面异常: Exception in thread "main" java.util.ConcurrentModificationExceptio ...

  8. java.util.ConcurrentModificationException异常;java.util.ConcurrentModificationException实战

    写代码遇到这个问题,很多博客文章都是在反复的强调理论,而没有对应的实例,所以这里从实例出发,后研究理论: 一.错误产生情况 1 .字符型 (1)添加 public static void main(S ...

  9. java.util.ConcurrentModificationException异常的解决

    问题复现: List<String> list = new ArrayList<>();list.add("11");list.add("55&q ...

随机推荐

  1. Codevs 2894 Txx考试

    时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题目描述 Description Txx是一个成绩很差的人,考试便成了他的噩梦.于是他常在考试时睡觉以打发时间.今天 ...

  2. floodfill算法解题示例

    Flood fill算法是从一个区域中提取若干个连通的点与其他相邻区域区分开(或分别染成不同颜色)的经典算法.因为其思路类似洪水从一个区域扩散到所有能到达的区域而得名.在GNU Go和扫雷中,Floo ...

  3. android activity空指针异常解决问题解决

    今天在开发过程中,遇到了一个错误 unable to instantiate activity componentinfo java.lang.nullpointerexception google之 ...

  4. WP开发笔记——字符串 转 MD5 加密

    将字符串进行MD5加密,返回加密后的字符串. 从这里下载Md5.cs文件:http://pan.baidu.com/s/1hq3gpnu. 添加到Windows Phone 7项目中,在代码里面这样调 ...

  5. 取代file_get_contents 的一个采集函数

    function url_get_content($url=''){ $ch = curl_init(); $timeout = 100; $browser = 'Mozilla/5.0 (Windo ...

  6. ADO.NET基本操作(CRUD、Procedure、Transaction)

    模型沿用上篇博客所提到的学生.教师.课程,以详细的代码进行演示. 增删改查 添加学生.教师.课程 using System.Data.SqlClient; namespace Test { class ...

  7. PHP连接SQL Server(sqlsrv)

    配置好php环境后,下载如下依赖包,解压目录选择php的ext目录,并在php.ini中加上(我的php版本为5.6) extension=php_pdo_sqlsrv_56_ts.dll exten ...

  8. Python开发【第一篇】Python模块中特殊变量

    模块中特殊变量 生产环境中,常用的就是__name__和__file__ __doc__ __package__ __cached__ __name__ __file__ 一. __doc__  #获 ...

  9. 开源免费的C/C++网络库(c/c++ sockets library)

    (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html (2)Asio Asio基于Boo ...

  10. ApacheBench 使用教程

    ab压力测试 ab是Apache超文本传输协议(HTTP)的性能测试工具.其设计意图是描绘当前所安装的Apache的执行性能. 主要是显示你安装的Apache每秒可以处理多少个请求. 格式: ./ab ...