如何产生,一边遍历一边修改元素,产生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. go语言学习--map的并发

    go提供了一种叫map的数据结构,可以翻译成映射,对应于其他语言的字典.哈希表.借助map,可以定义一个键和值,然后可以从map中获取.设置和删除这个值,尤其适合数据查找的场景.但是map的使用有一定 ...

  2. NFS应用场景及环境搭建

    两台虚拟机,一台做服务端(server)用来存储,一台做客户端(client)用来访问. 注意,两台虚拟机都已经挂载完光盘,并配置好yum源.客户端client已经安装好lamp环境,服务端不做任何处 ...

  3. JavaScript中的类(class)、构造函数(constructor)、原型(prototype)

    类 Class 类的概念应该是面向对象语言的一个特色,但是JavaScript并不像Java,C++等高级语言那样拥有正式的类,而是多数通过构造器以及原型方式来仿造实现.在讨论构造器和原型方法前,我可 ...

  4. [UE4]创建游戏、加入游戏

    google搜: UE4 compile dedicated server,编译UE4专用服务器 UE4默认网络端口可以在引擎配置文件中修改: 一.创建文件.需要修改一下工程的配置文件DefaultE ...

  5. typescript泛型接口

    //函数类型接口 /* interface ConfigFn{ (value1:string,value2:string):string; } var setData:ConfigFn=functio ...

  6. centos7 使用二进制安装mysql 5.7.23

    1.下载二进制安装包 mysql-5.7.23-linux-glibc2.12-x86_64.tar.gz cd /usr/local/src wget https://cdn.mysql.com// ...

  7. 关于dict的formkeys方法注意

    使用容器中的元素生成k, v为统一值, 指向同一个内存地址 默认值指向同一个内存, 修改就全部修改 strvar = 'abcd' listvar = [] dictvar = {} dictvar ...

  8. spark streaming的有状态例子

    import org.apache.spark._ import org.apache.spark.streaming._ /** * Created by code-pc on 16/3/14. * ...

  9. U3D学习005——输入操作

    1.input管理器 edit-project settings-input 2.getaxis——虚拟轴获取 获取水平和垂直的输入和其他输入(input管理器中定义的) 3.对象的transform ...

  10. Android WebView无法播放视频或直播,关闭界面后任在播放的问题;

    1.设置webview属性: webView.setWebChromeClient(new MyWebChromeClient());         webSettings = webView.ge ...