fail-fast简介

fail-fast出现场景

  • 单线程场景
    •     public class FailFastSingleThreadTest {
              public static void main(String[] args) {
                  List<String> lists = new ArrayList<>(10);
                  for (int i = 0; i < 4; i++){
                      lists.add(String.valueOf(i));
                  }
      
                  //fail-fast
                  for (String list : lists) {
                      lists.remove(3);
                  }
              }
          }
      //output:Exception in thread "main" java.util.ConcurrentModificationException
  • 多线程场景
    •   public class FailFastMultiThread  {
            private static List<String> lists = new ArrayList<>(10);
            static {
                for (int i = 0; i < 4; i++){
                    lists.add(String.valueOf(i));
                }
            }
            public static void main(String[] args) {
                new Thread(new ForEachThread()).start();
                new Thread(new EditThread()).start();
            }
      
            //用于遍历
            static class ForEachThread implements Runnable{
                @Override
                public void run() {
                    Iterator<String> iterator = lists.iterator();
                    while (iterator.hasNext()){
                        System.out.println(iterator.next());
                        try {
                            Thread.sleep(100);//为了另外的线程加入,也是为了结合在遍历时候修改结构
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
      
                }
            }
      
            //用于修改结构
            static class EditThread implements Runnable{
                @Override
                public void run() {
                    lists.add("8");
                }
            }
      
        }
        //output:Exception in thread "Thread-0" java.util.ConcurrentModificationException

      产生原因

        //省略部分方法
        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;
      
            @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();
            }
        }

解决方法

  • 单线程
    • 使用迭代器的remove方法
      public class NoFailFastSingleThread {
          public static void main(String[] args) {
              List<String> lists = new ArrayList<>(10);
              for (int i = 0; i < 4; i++){
                  lists.add(String.valueOf(i));
              }
    
              Iterator<String> iterator = lists.iterator();
              while (iterator.hasNext()){
                  String next = iterator.next();
                  if (next != null){
                      iterator.remove();
                  }
              }
    
          }
      }
  • 多线程
    • 使用java并发包下的类来代替对应的集合,如CopyOnWriteArrayList代替ArrayList,
12-18 20:24