ConcurrentModificationException原因及排除
如何产生,一边遍历一边修改元素,产生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原因及排除的更多相关文章
- Java并发-ConcurrentModificationException原因源码分析与解决办法
一.异常原因与异常源码分析 对集合(List.Set.Map)迭代时对其进行修改就会出现java.util.ConcurrentModificationException异常.这里以ArrayList ...
- 遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置
在以下四种遍历过程中,前两种会抛出ConcurrentModificationException,而后两种方法是正确的. Department类: package com.sitinspring; i ...
- [nagios监控] NRPE: Unable to read output 的原因及排除
nrpe被监控端运行定义命令正常,监控端运行 #/usr/local/nagios/libexec/check_nrpe -H 117.121.9.200 -c check_oracle_tables ...
- 偶遇到 java.util.ConcurrentModificationException 的异常
今天在调试程序 遇到了如此问题 贴上代码来看看稍后分析 List<String> list = null;boolean isUpdate = false;try { list = JSO ...
- Java处理java.util.ConcurrentModificationException异常
代码: public static void reduce(HashMap<String, Integer> hashMap, final Integer count) { Iterato ...
- Gradle-5.3:依赖-管理依赖的版本(传递(transitive)\排除(exclude)\强制(force)\动态版本(+))
什么是传递依赖 在Maven仓库中,构件通过POM(一种XML文件)来描述相关信息以及传递性依赖.Gradle 可以通过分析该文件获取获取所以依赖以及依赖的依赖和依赖的依赖的依赖,为了更加直观的表述, ...
- 对连接到 Azure 中 Linux VM 时出现的问题进行详细的 SSH 故障排除的步骤
有许多可能的原因会导致 SSH 客户端无法访问 VM 上的 SSH 服务. 如果已经执行了较常规的 SSH 故障排除步骤,则需要进一步排查连接问题. 本文指导用户完成详细的故障排除步骤,以确定 SSH ...
- Android Studio连接真机没反应?
刚好遇到这个问题,在网上百度了一下,看到有人分享了引起该问题的几个原因: 手机设置问题.开USB调试 方法: 手机设置 - 开发人员选项 - USB调试 - 勾选 数据线问题. 有的数据线只能用来充电 ...
- ARCGIS Server 发布服务时出现的问题解决
target='CFH.ConfigurationFactoryHost' machine='IBM3850X5' thread='24072' elapsed='0.31200'>Ser ...
随机推荐
- [转][C#]BarCodeToHTML
/// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:http://www.sufeinet.c ...
- [UE4]Datasmith
Datasmith 是帮助您将内容导入到虚幻引擎4中的一组工具和插件. 作为虚幻工作室产品的部分,Datasmith设计用于解决非游戏行业人士所面临的独特挑战,例如建筑.工程.建造.制造.实时培训等行 ...
- Android Studio启动后出现cannot bind to 127.0.0.1:5037 10048的解决办法
第一次:先连接测试手机,然后启动Android studio时出现下面的弹框,网上查找资料说是360手机助手导致的,但是发现没有安装360手机助手只有360,卸载360后再启动Android stud ...
- c#特性学习(1)
C#中的特性我认为可以理解为Java中的注解,见名知意,就是描述这个类或是属性的一个信息,是一个语法糖.原理运用的是反射,下面我来演示一下它的原理.其中引用了软谋的代码. 举一个栗子.我们在做code ...
- springmvc前端控制器的三种拦截方式
*.do :只拦截.do文件 / :拦截除jsp页面的所有请求,包括restful类型的url /* :拦截所有请求包括jsp页面
- WebSocket 跨域
http://www.cnblogs.com/joeymary/p/5259464.html
- list函数
列表的切片: 获取: 1. [start:] 2. [:end] 3. [statr:end] 4. [statr: end: spet] 修改: listvar[:2] = ' 把0~1索引元素删除 ...
- Delphi获取本机的MAC地址
Delphi获取本机的MAC地址: uses NB30; function GetAdaPterInfo(lana: Char): string; var Adapter: TAdapterS ...
- virt-install vs qemu-kvm创建guest主机
virt-install是rpm包python-virtinst里的一个工具 -- 其实就是一个python写的脚本 .基本可以理解为virsh-install是qemu-kvm工具的人性化实现.可以 ...
- vmware workstation14嵌套安装kvm
1.前言 我在2017-11-06使用virtualbox安装了centos,然后嵌套kvm(win7),链接地址如下: https://www.cnblogs.com/tcicy/p/7790956 ...