并发修改异常的源码分析
并发修改异常:ConcurrentModificationException
产生原因:迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案:用for循环遍历,然后用集合对象做对应操作即可
import java.util.ArrayList; import java.util.Iterator; import java.util.List; /* 需求: 我有一个集合: List<String> list = new ArrayList<String>(); 里面有三个元素: list. add( "hello");list. add( "world");list. add( "java"); 遍历集合,得到每一个元素,看有没有"world"这个元素,如果有,我就添加一个"javaee“元素,请写代码实现 //ConcurrentModificationException:当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常。 */ public class ListDemo_1 { 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循环遍历 // while (it.hasNext()){ // String s=it.next();//ConcurrentModificationException:并发修改异常 //① // if (s.equals("world")){ // list.add("javaee"); // } // }
//for循环遍历 for (int i = 0; i < list.size(); i++) { String s=list.get(i); if (s.equals("world")){ list.add("javaee"); } } System.out.println(list); //[hello, world, java, javaee] } }
并发修改异常源码分析
public interface List<E>{ Iterator<E> iterator(); boolean add(E e); } public abstract class AbstractList<E>{ protected int modCount=0;//:③-1此处定义modCount初始值 } public class ArrayList<E> extends AbstractList<E> implements List<E>{ public E get(int index) {//⑤:修改后:没有实际修改值和预期修改值的判断,故不会抛出异常 Objects.checkIndex(index, size); return elementData(index); } public boolean add(E e) {//③:调用add(),中modCount数值改变。原本数值是ArrayList继承的父类中的属性值=0。 modCount++; add(e, elementData, size); return true; } public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int expectedModCount = modCount; /* modCount:实际修改结合的次数 expectedModCount:预期修改集合的次数 */ public E next() {//②:调用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(); } } }