fail-fast

fail-fast机制

- java集合(Collection)中的一种错误机制
- 当多个线程对同一个集合的内容进行操作时,就可能产生fail-fast事件
- 只能用来检测错误
  • 测试代码
    public class Test {
    
        private static List<String> list = new ArrayList<>();
    
        /**
        * @Description:  打印list内容
        */
        public static void showAll(){
            System.out.println("\nnum is ");
            String num = null;
            Iterator iterator = list.iterator();
            while(iterator.hasNext()){
                num = (String) iterator.next();
                System.out.print(num + " ");
            }
        }
    
        /**
        * @Description: 往list中添加数据,并打印list中数据
        */
        public static class ThreadOne extends Thread{
            public void run(){
                int index = 0;
                while(index < 10){
                    list.add(String.valueOf(index));
                    showAll();
                    ++index;
                }
            }
        }
    
        public static class ThreadTwo extends Thread{
            public void run(){
                int index = 10;
                while(index < 20){
                    list.add(String.valueOf(index));
                    showAll();
                    ++index;
                }
            }
        }
    
        public static void main(String[] args) {
            // 同时启动两个线程操作list
            new ThreadOne().start();
            new ThreadTwo().start();
        }
    }
    
    • 运行代码。抛出异常java.util.ConcurrentModificationException,即fail-fast事件
    • 若想在多线程环境下使用fail-fast机制的集合
      // 原代码
      private static List<String> list = new ArrayList<String>();
      // 修改为
      private static List<String> list = new CopyOnWriteArrayList<String>();
      
  • fail-fast原理
    • ArrayList的Iterator是在父类AbstractList.java中实现
      package java.util;
      public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
      
          /**
           * 部分源码
           */
      
          // 记录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();
              }
          }
      }
      
    • ArrayList源码,modCount被修改
      package java.util;
      
      public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
      {
      
          /**
           * 部分源码
           */
           
          // list中容量变化时,对应的同步函数
          public void ensureCapacity(int minCapacity) {
              modCount++;
              int oldCapacity = elementData.length;
              if (minCapacity > oldCapacity) {
                  Object oldData[] = elementData;
                  int newCapacity = (oldCapacity * 3)/2 + 1;
                  if (newCapacity < minCapacity)
                      newCapacity = minCapacity;
                  // minCapacity is usually close to size, so this is a win:
                  elementData = Arrays.copyOf(elementData, newCapacity);
              }
          }
      
      
          // 添加元素到队列最后
          public boolean add(E e) {
              // 修改modCount
              ensureCapacity(size + 1);  // Increments modCount!!
              elementData[size++] = e;
              return true;
          }
      
      
          // 添加元素到指定的位置
          public void add(int index, E element) {
              if (index > size || index < 0)
                  throw new IndexOutOfBoundsException(
                  "Index: "+index+", Size: "+size);
      
              // 修改modCount
              ensureCapacity(size+1);  // Increments modCount!!
              System.arraycopy(elementData, index, elementData, index + 1,
                   size - index);
              elementData[index] = element;
              size++;
          }
      
          // 添加集合
          public boolean addAll(Collection<? extends E> c) {
              Object[] a = c.toArray();
              int numNew = a.length;
              // 修改modCount
              ensureCapacity(size + numNew);  // Increments modCount
              System.arraycopy(a, 0, elementData, size, numNew);
              size += numNew;
              return numNew != 0;
          }
         
      
          // 删除指定位置的元素 
          public E remove(int index) {
              RangeCheck(index);
      
              // 修改modCount
              modCount++;
              E oldValue = (E) elementData[index];
      
              int numMoved = size - index - 1;
              if (numMoved > 0)
                  System.arraycopy(elementData, index+1, elementData, index, numMoved);
              elementData[--size] = null; // Let gc do its work
      
              return oldValue;
          }
      
          // 快速删除指定位置的元素 
          private void fastRemove(int index) {
      
              // 修改modCount
              modCount++;
              int numMoved = size - index - 1;
              if (numMoved > 0)
                  System.arraycopy(elementData, index+1, elementData, index,
                                   numMoved);
              elementData[--size] = null; // Let gc do its work
          }
      
          // 清空集合
          public void clear() {
              // 修改modCount
              modCount++;
      
              // Let gc do its work
              for (int i = 0; i < size; i++)
                  elementData[i] = null;
      
              size = 0;
          }
      }        
      
    • 可以发现涉及到修改集合中的元素个数时,都会改变modCount的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值