文章目录
ConcurrentModificationException并发修改异常
当我们对集合进行迭代(遍历)的时候,同时(并发)对集合进行修改,就会产生并发修改
比如说遍历一个集合时,同时对其中一个元素删除,修改等等操作。
或者 list 在多线程情况下 既有读又有写,报出ConcurrentModificationException问题,
概括来说分为两种情况
- 一边遍历集合,而另一边在修改集合时,会报ConcurrentModificationException错误
- 在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据,因此会报ConcurrentModificationException错误。
modCount:
这个数是结构化修改的次数,结构修改是指改变列表的大小,或者以一种可能产生错误结果的方式扰乱列表。
expectedModCount:
期望修改的次数
当添加add或删除元素remove来修改集合,那么modCount将更改,赋值给expectedModCount。
当多线程时,有的线程没写进去集合的size(大小)没变,有的线程写进去集合的size(大小)变了,导致计数器modCount的值发生了改变并不是有序+1,但是往出输出时,导致了expectedModCount与modCount两个计数器不相同,于是返回ConcurrentModificationE错误。
迭代器认为支持的modCount值列表应有。如果违背此期望,则迭代器检测到并发修改。
5.1List集合的线程不安全
public class ArrayList {
public static void main(String[] args) {
//创建ArrayList集合
List<String> list = new java.util.ArrayList<>();
for (int i = 0; i <30; i++) {
new Thread(()->{
//向集合添加内容
list.add(UUID.randomUUID().toString().substring(0,8));
//从集合获取内容
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
异常内容:
java.util.ConcurrentModificationException ---->>并发修改异常
①,使用Vector解决
Vector 是矢量队列,它是 JDK1.0 版本添加的类。继承于 AbstractList,实现了 List, RandomAccess, Cloneable 这些接口。 Vector 继承了 AbstractList, 实现了 List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能**。 Vector 实现了 RandmoAccess 接口,即提供了随机访问功能。 RandmoAccess 是 java 中用来被 List 实现,为 List 提供快速访问功能的。在Vector 中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访 问。 Vector 实现了 Cloneable 接口,即实现 clone()函数。它能被克隆。
public class ArrayList {
public static void main(String[] args) {
//创建ArrayList集合
List<String> list = new Vector<>();
for (int i = 0; i <30; i++) {
new Thread(()->{
//向集合添加内容
list.add(UUID.randomUUID().toString().substring(0,8));
//从集合获取内容
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
深入Vector可以发现:add方法含有synchronized锁,可以增强线程