一、问题引入
ArrayList的四个基础操作——增删改查
初始化
static ArrayList<Student> students = new ArrayList<Student>();
//初始化
//添加部分学生对象实例
static {
students.add(new Student("张三", "男", 17));
students.add(new Student("李四", "男", 18));
students.add(new Student("王五", "女", 19));
students.add(new Student("云九", "男", 23));
}
查找:
//查找“云九”
public static void find(){
for (Student student : students) {
if(student.getName().equals("云九")){
System.out.println(student.toString());
}
}
}
运行结果
修改:
//找到“云九”,将其年龄修改为18
//修改
public static void modify(){
for (Student student : students) {
if(student.getName().equals("云九")){
student.setAge(18);
System.out.println(student.toString());
}
}
}
运行结果
添加:
//如果有“云九”,则添加一个学生“肖八”
//添加学生
public static void add(){
for (Student student : students) {
if(student.getName().equals("云九")){
students.add(new Student("肖八", "男", 22));
}
}
}
运行结果
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
at java.util.ArrayList$Itr.next(ArrayList.java:861)
删除:
//找到“云九”,将其删除
public static void delete(){
for (Student student : students) {
if(student.getName().equals("云九")){
students.remove(student);
}
}
}
运行结果
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
at java.util.ArrayList$Itr.next(ArrayList.java:861)
二、原因分析
由此,ArrayList的四种基本操作增删改查,其中的增和删都出现了ConcurrentModificationException,也就是并发修改异常,仔细查看抛出的异常,我们可以发现错误都指向了ArrayList内部类Itr的next方法当中的checkForComodification方法
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
看到next方法,首先联想到迭代器Iterator,但是以上都是通过for-each进行遍历的,所以这里还涉及到for-each的内部实现问题, for-each的底层其实也是通过迭代器实现的(java foreach内部实现_山间明月江上清风_的博客-CSDN博客),也就是说当我们在使用简洁for循环或者通过迭代器遍历时,都会先调用迭代器的next方法,在next方法中又会首先调用checkForComodification()方法进行检查,当这个方法检查到modCount与expectedModCount不相等时,就会抛出并发修改异常。
由此可知,并发修改异常的实质是一个名为modCount的变量值不再等于expectedModCount的变量值
modCount
进一步查看源码可以知道modCount是定义在AbstractList抽象类中的成员变量,而Arra