如何产生,一边遍历一边修改元素,产生iter后再修改原结构,如下,无论是for中或iter都会产生ConcurrentModificationException

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; /**
* Created by itworker365 on 5/16/2017.
*/
public class ConcurrentModifyException {
public static void main(String[] args) throws InterruptedException {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
final List<String> list = new ArrayList<String>(a);
final Iterator<String> it = list.iterator();
//cause ConcurrentModifyException,list.iterator已经生成iterator对象,此时再更改原结构报错
a.add("d");
Thread t = new Thread(new Runnable() {
int count = -1;
@Override
public void run() {
if (list.contains("a")) {
list.remove("a");
}
}
});
t.setDaemon(true);
t.start(); for (String s : list) {
//cause ConcurrentModifyException,边读边改报错
System.out.println(list.hashCode() + " " + s);
}
// while (it.hasNext()) {
// //cause ConcurrentModifyException,边读边改报错
// System.out.println(it.next());
// }
}
}

产生原因:

        public E next() {
checkForComodification();
            if (modCount != expectedModCount)
throw new ConcurrentModificationException();

解决办法:

1. 用CopyOnWriteArrayList, 可以发现在打印hashcode的时候并不相同,这种结构在修改元素时使用Arrays.CopyOf复制元素,然后在新List中修改之后修改引用

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; /**
* Created by itworker365 on 5/16/2017.
*/
public class ConcurrentModifyException {
public static void main(String[] args) throws InterruptedException {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
final List<String> list = new CopyOnWriteArrayList<String>(a);
final Iterator<String> it = list.iterator();
Thread t = new Thread(new Runnable() {
int count = -1;
@Override
public void run() {
if (list.contains("a")) {
list.remove("a");
}
}
});
t.setDaemon(true);
t.start();
for (String s : list) {
System.out.println(list.hashCode() + " " + s);
}
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

CopyOnWriteArrayList关键实现,一看既懂,需要注意的是内存使用,可能复制后会出发gc,因为写操作完成并且引用指向新数组之前,其他并发读取线程只能看到旧数据,所以只是最终一致性,不能实时。

private volatile transient Object[] array;
    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();
}
}
    final void setArray(Object[] a) {
array = a;
}

2. 使用Iterator去除,迭代器支持的功能有限

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; /**
* Created by itworker365 on 5/16/2017.
*/
public class ConcurrentModifyException {
public static void main(String[] args) throws InterruptedException {
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
final List<String> list = new ArrayList<String>(a);
final Iterator<String> it = list.iterator();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (it.hasNext()) {
String xx = it.next();
it.remove();
}
}
});
t.setDaemon(true);
t.start();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

ConcurrentModificationException原因及排除的更多相关文章

  1. Java并发-ConcurrentModificationException原因源码分析与解决办法

    一.异常原因与异常源码分析 对集合(List.Set.Map)迭代时对其进行修改就会出现java.util.ConcurrentModificationException异常.这里以ArrayList ...

  2. 遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置

    在以下四种遍历过程中,前两种会抛出ConcurrentModificationException,而后两种方法是正确的. Department类: package com.sitinspring; i ...

  3. [nagios监控] NRPE: Unable to read output 的原因及排除

    nrpe被监控端运行定义命令正常,监控端运行 #/usr/local/nagios/libexec/check_nrpe -H 117.121.9.200 -c check_oracle_tables ...

  4. 偶遇到 java.util.ConcurrentModificationException 的异常

    今天在调试程序 遇到了如此问题 贴上代码来看看稍后分析 List<String> list = null;boolean isUpdate = false;try { list = JSO ...

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

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

  6. Gradle-5.3:依赖-管理依赖的版本(传递(transitive)\排除(exclude)\强制(force)\动态版本(+))

    什么是传递依赖 在Maven仓库中,构件通过POM(一种XML文件)来描述相关信息以及传递性依赖.Gradle 可以通过分析该文件获取获取所以依赖以及依赖的依赖和依赖的依赖的依赖,为了更加直观的表述, ...

  7. 对连接到 Azure 中 Linux VM 时出现的问题进行详细的 SSH 故障排除的步骤

    有许多可能的原因会导致 SSH 客户端无法访问 VM 上的 SSH 服务. 如果已经执行了较常规的 SSH 故障排除步骤,则需要进一步排查连接问题. 本文指导用户完成详细的故障排除步骤,以确定 SSH ...

  8. Android Studio连接真机没反应?

    刚好遇到这个问题,在网上百度了一下,看到有人分享了引起该问题的几个原因: 手机设置问题.开USB调试 方法: 手机设置 - 开发人员选项 - USB调试 - 勾选 数据线问题. 有的数据线只能用来充电 ...

  9. ARCGIS Server 发布服务时出现的问题解决

    target='CFH.ConfigurationFactoryHost'  machine='IBM3850X5'  thread='24072'  elapsed='0.31200'>Ser ...

随机推荐

  1. [UE4]小地图UI设计

    一.新建一个名为TestMiniMap的UserWidget用来使用小地图StaticMiniMap. 二.在左侧“User Created”面板中可以看到除自身以外的其他所有用户创建的UserWid ...

  2. [UE4]场景加载界面

    就可以这样就可以了,当另外一个场景成功打开后,场景加载界面也会自动消失(因为这是加载界面是添加到当前场景). 加上delay是为了在小场景测试的时候可以方便看到加载场景,避免场景加载过快看不到,不加的 ...

  3. 从MediaStorehe和sd中删除媒体文件

    参考资料:http://www.sandersdenardi.com/querying-and-removing-media-from-android-mediastore/ 从媒体表中删除: pri ...

  4. Ext.NET Combobox实现数据源静态配置

    背景 项目中使用增值税税率, 需求原本是统一的指定税率, 譬如3% 5% 等固定的. 随着业务增加, 发现不同业务有不同的税率, 一会加一个, 一下要改很多个界面. 就想着放到统一的地方. 技术背景 ...

  5. (转)C# BackgroundWorker组件的原理分析

    原文地址:http://www.cnblogs.com/chaosimple/archive/2012/11/30/2796069.html 主要属性: 1.CancellationPending 获 ...

  6. lambda详解

    1:lambda表示方法 auto lambda = [](){}; lambda(); sizeof(lambda) = 1; 等价于类 class lambda{ pulic operator() ...

  7. python多进程与服务器并发

    进程 什么是进程 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 进程与程序的区别 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程. 并发与并行 无论是并行还是并发,在用户看 ...

  8. win7禁用Adnimistrator账号登录

    开始 运行 输入 lusrmgr.msc 回车. 双击 用户,双击Administrator ,在 账户已禁用 前面打上勾即可.然后确定.

  9. 3-安装hive

    1.解压.修改权限 tar -zvxf apache-hive-1.2.1-bin.tar.gz -C /opt/app/ sudo chown -R hadoop:hadoop /opt/app/a ...

  10. Ubuntu 16.04 fatal: Unable to find remote helper for 'https'

    在Windows10 的Linux子系统下安装oh-my-zsh的时候出现如下错误: fatal: Unable to find remote helper for 'https' 网上有描述说没有安 ...