码迷,mamicode.com
首页 > 编程语言 > 详细

Java集合三fail-fast

时间:2018-04-16 13:01:10      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:个数   抛出异常   执行   遍历   pac   原理   检测   等于   write   

fail-fast

  fail-fast机制是java集合中的一种错误机制。当多个线程对统一集合的内容进行操作时,就可能会产生fail-fast事件。
?? 当某一个线程通过iterator遍历某个集合时,该集合的线程被其他线程改变了,就会抛出异常,产生fail-fast事件。

fail-fast解决办法

  fail-fast机制是一种错误检测机制,用来检测错误,JDK并不保证fail-fast机制一定会发生。如果在多线程环境下使用fail-fast机制的集合,建议使用java.util.concurrent包下的类。

fail-fast原理

package java.util;

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {

    ...

    // AbstractList中唯一的属性
    // 用来记录List修改的次数:每修改一次(添加/删除等操作),将modCount+1
    protected transient int modCount = 0;

    // 返回List对应迭代器。实际上,是返回Itr对象。
    public Iterator<E> iterator() {
        return new Itr();
    }

    // Itr是Iterator(迭代器)的实现类
    private class Itr implements Iterator<E> {
        int cursor = 0;

        int lastRet = -1;

        // 修改数的记录值。
        // 每次新建Itr()对象时,都会保存新建该对象时对应的modCount;
        // 以后每次遍历List中的元素的时候,都会比较expectedModCount和modCount是否相等;
        // 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
        int expectedModCount = modCount;

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

        public E next() {
            // 获取下一个元素之前,都会判断“新建Itr对象时保存的modCount”和“当前的modCount”是否相等;
            // 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
            checkForComodification();
            try {
                E next = get(cursor);
                lastRet = cursor++;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

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

    ...
}

  在调用next()和remove()时,都会执行checkForComodification()。如果modCount不等于expectedModCount,就会抛出异常,产生fail-fast事件。
  expectedModCount在创建Itr对象时,被赋值为modCount。而expectedModCount不可能被修改,所以需要知道modCount何时被改变。
  查看ArrayList源码,可以得知add()、remove()等设计到修改集合中元素个数的操作,都会改变modCount的值。

解决fail-fast的原理

  以ArrayList对应的CopyOnWriteArrayList为例,通过观察源码可知:
  1、ArrayList继承AbstractList,而CopyWriteArrayList没有继承AbstractList,仅仅只是实现了List接口
  2、ArrayList的iterator()函数返回的Iterator是在AbstractList中实现的,而CopyOnWriteArrayList是自己实现的Iterator
  ArrayList的Iterator实现类中调用next()时,会“调用checkForComodification()比较‘expectedModCount’和‘modCount’的大小”;但是,CopyOnWriteArrayList的Iterator实现类中,没有所谓的checkForComodification(),更不会抛出ConcurrentModificationException异常
  CopyOnWriteArrayList对会改变集合元素的操作都使用synchronized关键字进行了同步,保证了线程安全

参考自:http://www.cnblogs.com/skywang12345/p/3323085.html

Java集合三fail-fast

标签:个数   抛出异常   执行   遍历   pac   原理   检测   等于   write   

原文地址:https://www.cnblogs.com/changzuidaerguai/p/8855232.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!