并发修改异常
【摘要】 <2>并发修改异常先来看一个代码package java_practice;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class ListDemo { public static void main(String args[]) { List<Str...
<2>并发修改异常
先来看一个代码
package java_practice;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListDemo {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("world");
list.add("java");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String s = it.next();
if(s.equals("world"))
{
list.add("javaee");
}
}
// for(int i=0;i<list.size();i++)
// {
// String s = list.get(i);
// if(s.equals("world"))
// {
// list.add("javaee");
// }
//
// }
System.out.println(list);
}
}
很显然这里抛出了异常,为什么会这样呢?
下面摘录异常信息
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:907)
at java.util.ArrayList$Itr.next(ArrayList.java:857)
at java_practice.ListDemo.main(ListDemo.java:16)
我们根据checkForComodification步步跟进源码
下面是跟进和溯源处理后的关键源码信息
public interface List<E>{
Iterator<E> iterator();
boolean add(E e)
}
public abstract class AbstractList<E>
{
protected transient int modCount = 0;
}
public class ArrayList<E> extends AbstractList<E>implements List<E>
{
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!//每次调用add()会使modCount++
elementData[size++] = e;
return true;
}
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int expectedModCount = modCount;
//modCount为实际修改集合的次数
//expectedModCount为预期修改集合的次数
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)
//modCount为修改集合的次数,exceptedModCount为预期修改集合的次数
throw new ConcurrentModificationException();
}
}
/**
}
源码很清楚了,而且我做了部分注释,可以自己捋一下。原因就是,我们采用迭代器的时候,迭代器会有一个预期的迭代次数,当我们进行在迭代的同时进行添加的时候会调用add()方法的话,就会modCount++(实际迭代次数),但是expectedModCount(预期迭代次数)没有进行处理同步,造成了数据不一致,源码也说明了,如果不一致,就会抛出异常。
提出一种解决的办法,避免数据不一致,比如for循环。
package java_practice;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListDemo {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("Hello");
list.add("world");
list.add("java");
Iterator<String> it = list.iterator();
// while(it.hasNext()) {
// String s = it.next();
// if(s.equals("world"))
// {
// list.add("javaee");
// }
//
//}
for(int i=0;i<list.size();i++)
{
String s = list.get(i);
if(s.equals("world"))
{
list.add("javaee");
}
}
System.out.println(list);
}
}
可能在这里你可能有疑问,get()俩面不也有add()吗?为什么不报异常。上面源码也摘录出来了。原因就是我们调用了集合的add()方法,实际上会使实际迭代次数加一的,但是get()函数里面没有进行实际与预期的判断,也自然不会抛出异常,可以参考上诉源码,明明白白。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)