前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ArrayList的Fast-fail(快速失败)策略

ArrayList的Fast-fail(快速失败)策略

作者头像
用户6055494
发布2019-10-21 14:23:04
1.7K0
发布2019-10-21 14:23:04
举报
文章被收录于专栏:AVAJAVAJ
什么是快速失败:fail-fast 机制是java集合(Collection)中的一种错误机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。

1、运行如下代码,即可出现异常:

代码语言:javascript
复制
// 关于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定位到该处代码:

代码语言:javascript
复制
final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

4、modCount是这个集合修改的次数,这个属性来自AbstractList,而我们的ArrayList是继承了该抽象类的。

代码语言:javascript
复制
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异常。好啦以上就是快速失败啦,感谢宝贵时间!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员面试鸭 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档