如何产生,一边遍历一边修改元素,产生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. 学习笔记之Bokeh

    Welcome to Bokeh — Bokeh 0.12.16 documentation https://bokeh.pydata.org/en/latest/ Bokeh is an inter ...

  2. 网站首页多URL可访问,如何集中首页网站权重?

    原文地址:http://ask.seowhy.com/question/8573 百度站长平台Lee在文章<建立符合搜索引擎抓取习惯>一文中提出:唯一性网站中同一内容页只与唯一一个url相 ...

  3. RecyclerAdapter封装

    import java.util.LinkedList; import java.util.List; import android.content.Context; import android.s ...

  4. CountDownLatch的简单讲解

    正如每个Java文档所描述的那样,CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行.在Java并发中,countdownlatch的概念是一 ...

  5. android adb push 命令

    1.获得root权限:adb root 2.设置/system为可读写:adb remount 3.将PC机上文件复制到手机:adb push 文件名  /system/lib

  6. Type Cannot change version of project facet Dynamic Web Module to 2.5 报错

    项目下的.setings文件 夹中的 version 改为2.5

  7. Mysql之 配置文件读取顺序

    On Unix, Linux and Mac OS X, MySQL programs read startup options from the following files, in the sp ...

  8. Linux聚合网络

    Linux聚合网络 作者:Eric 微信:loveoracle11g 链路聚合 [root@server1 ~]# ifconfig | grep eno [root@server1 ~]# ls / ...

  9. 给 Windows 文件菜单添加 "用XX程序打开" "用XX编辑" "用XX运行"

    有什么用就不用多说了,这可是个很有用的技巧.可以创造自己的文件格式,也可以给已有的文件添加多种打开方式 在注册表[HKEY_CLASSES_ROOT]下找到或者建立对应的扩展名 如果想对所有文件都生效 ...

  10. babel-polyfill

    babel-polyfill Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator.Generator.Set.Maps.Proxy.Reflec ...