229 «并发修改异常
(这节课很复杂,半懂)
【课程思路】
代码:创建集合、输入3个元素、if循环/如果元素里有某元素则add某元素
代码运行:报错ConcurrentModificationExpection
并发修改异常的源码分析
按报错原因搜索,收集相关类、方法的源码,找到报错的原因,关键源码;
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
--------------------------------------------------------------
package e229;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// 思路
// 1.创建list集合,,,2.添加3个元素,,,3.遍历集合查找Tracy,如果有Tracy则添加一个Ben
// # 并发修改异常源码分析
// Q:为什么用正确的思路写了代码,结果报错ConcurrentModificationException?
// 帮助文档搜索ConcurrentModificationException:
// > 当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出异常.由此可知,这是运行时异常
// 新建一个txt文件:package-new-file-text
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("229");
list.add("Hello");
list.add("Tracy");
// Iterator<String> it = list.iterator();
// while (it.hasNext()){
// String s = it.next();
// if (s.equals("Tracy")){
// list.add("Ben");
// }
// }//报错了,ConcurrentModificationException
// 改用for循环遍历
for (int i=0;i<list.size();i++){
String s = list.get(i);
//用get方法没有报错,
//因为查看ArrayList集合的get方法源码可知
//get方法的源码没有比较modCount和expectedModCount
if (s.equals("Tracy")){
list.add("Ben");
}
}
System.out.println("36.list:\n\t"+list);
}
}
--------------------------------------------------------------
36.list:
[229, Hello, Tracy, Ben]
--------------------------------------------------------------
List接口的iterator方法、add方法
ArrayList接口的iterator方法、itr内部类、add方法
留下itr内部类当中的next方法、checkForComodification方法,其他先删掉
public interface List<E> extends Collection<E> {
Iterator<E> iterator();
boolean add(E e);
}
public abstract class AbstractList<E>{
protected int modCount = 0;
}
public abstract class AbstractList<E>
public class ArrayList<E> extends AbstractList<E> implements List<E>,{
public boolean add(E e){
这里!!!
modCount++;
add(e,elementData,size);
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
//modCount,实际修改集合的次数,来自ArrayList集合的父类AbstractList
//expectedModCount,预期修改集合的次数
上面把modCount赋值给expectedModCount,故这两个变量的值相同
我们写的代码报错是因为我们的代码导致其中一个变量的值+1了,然后两个变量不一致了
可是源码并没有比较这两个变量啊?
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();
}
}
}
class ArrayList{
public E get(int index) {
Objects.checkIndex(index, size);
return elementData(index);
}
}
【insert】缩进
shift tab左移
tab右移