1、运行如下代码,即可出现异常:
// 关于fastFail的一些思考
public class FastFailTest {
public static void main(String[] args) {
// 构建ArrayList
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (int i : list) {
System.out.println(i);
list.remove(1);
}
}
}
2、控制台会输出如下异常:
3、为什么要报这个错?途中出错的地方是ArrayList.java:901定位到该处代码:
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
4、modCount是这个集合修改的次数,这个属性来自AbstractList,而我们的ArrayList是继承了该抽象类的。
protected transient int modCount = 0;
5、expectedModCount又是啥呢?当我们进行遍历时候debug一下发现进行forEach循环的时候其实走了下面这个方法iterator,而且遍历这个底层还是走的hasNext方法
6、点进这个new Itr(),惊喜的发现原来这个expectedModCount是在这里被赋值的而且和modCount一样
7、接下来看下ArrayList的remove()方法
8、ArrayList里面remove()方法进行了modCount++操作,原来是我们对集合进行操作后改变了modCount导致以下代码成立,从而抛出异常
9、但当我们使用Itr类的remove,也就是如下代码进行对元素改动时,不会抛出ConcurrentModificationException异常
10、点入remove()方法:
11、与ArrayList的remove()方法不同的是,该remove()方法调用ArrayList.this.remove(lastRet);后显然modCount++了,但是马上又让expectedModCount = modCount就是这样才不会抛出异常。
总结:可以使用CopyOnWriteArrayList来代替ArrayList,其所有可变操作(添加、设置,等等)都是通过对基础数组进行一次新的复制来实现的,所以不会抛ConcurrentModificationException异常。好啦以上就是快速失败啦,感谢宝贵时间!