动力节点首页 全国咨询热线:400-8080-105

绑定手机号,登录
手机号

验证码

微信登录
手机号登录
手机号

验证码

微信登录与注册
微信扫码登录与注册

扫码关注微信公众号完成登录与注册
手机号登录
首页 > 文章

简述Java集合的fail-fast机制

06-01 16:26 861浏览
举报 T字号
  • 大字
  • 中字
  • 小字

fail-fast 机制是Java集合(Collection)中的一种错误机制。 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的结构进行了修改(增加、删除),则会抛出Concurrent Modification Exception(并发修改异常)。

所以,在多线程环境下,是很容易抛出Concurrent Modification Exception的,比如线程1正在对集合进行遍历,此时线程2对集合进行修改(增加、删除)。但是,单线程就不会抛出吗?很明显,单线程也会有类似的情况,比如main线程在遍历时对集合进行修改(增加、删除、修改),那么main线程就会抛出Concurrent Modification Exception异常。

因为我们是在遍历的时候对集合修改会发生fail-fast,遍历集合一般都用迭代器,那就先看看迭代器的源码:

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;

    public boolean hasNext() {
        return cursor != size;
    }

    @SuppressWarnings("unchecked")
    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];
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

可以看到,罪魁祸首是checkForComodification这个方法,它是在modCount != expectedModCount的时候抛出了那该死的异常,而在next方法中第一句就是checkForComodification,所以遍历集合才会可能抛出并发修改异常。而且,在创建一个迭代器后,expectedModCount的初始值就是modCount了,对集合修改只会改变modCount,expectedModCount只会在迭代器的remove方法中被修改为modCount。

那么我们如何避免fail-fast抛异常呢?

1.如果非要在遍历的时候修改集合,那么建议用迭代器的remove等方法,而不是用集合的remove等方法。(老实遵守阿里巴巴java开发规范……)

2.如果是并发的环境,那还要对Iterator对象加锁;也可以直接使用Collections.synchronizedList。

3.CopyOnWriteArrayList(采用fail-safe)

0人推荐
共同学习,写下你的评论
0条评论
代码小兵124
程序员代码小兵124

99篇文章贡献336699字

相关课程 更多>

作者相关文章更多>

推荐相关文章更多>

Java面试题及答案整理

提枪策马乘胜追击04-21 20:01

Spring常见面试题

代码小兵92504-17 16:07

Java零基础实战项目——五子棋

代码小兵98804-25 13:57

Java string类详解

杨晶珍05-11 14:54

6道经典算法面试题

杨晶珍05-12 16:39

发评论

举报

0/150

取消