fail 您所在的位置:网站首页 java集合的作用是什么和什么的区别 fail

fail

2024-07-02 21:10| 来源: 网络整理| 查看: 265

fail-fast和fail-safe的区别: 

fail-safe允许在遍历的过程中对容器中的数据进行修改,而fail-fast则不允许。

fail-fast ( 快速失败 )

fail-fast:直接在容器上进行遍历,在遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出ConcurrentModificationException异常导致遍历失败。java.util包下的集合类都是快速失败机制的, 常见的的使用fail-fast方式遍历的容器有HashMap和ArrayList等。

在使用迭代器遍历一个集合对象时,比如增强for,如果遍历过程中对集合对象的内容进行了修改(增删改),会抛出ConcurrentModificationException 异常.

fail-fast的出现场景 在我们常见的java集合中就可能出现fail-fast机制,比如ArrayList,HashMap。在多线程和单线程环境下都有可能出现快速失败。 1、单线程环境下的fail-fast: ArrayList发生fail-fast例子:

public static void main(String[] args) {     List list = new ArrayList();     for (int i = 0 ; i < 10 ; i++ ) {         list.add(i + "");     }     Iterator iterator = list.iterator();     int i = 0 ;     while(iterator.hasNext()) {         if (i == 3) {              list.remove(3);         }         System.out.println(iterator.next());         i ++;     } } 

该段代码定义了一个Arraylist集合,并使用迭代器遍历,在遍历过程中,刻意在某一步迭代中remove一个元素,这个时候,就会发生fail-fast。

HashMap发生fail-fast:

public static void main(String[] args) {     Map map = new HashMap();     for (int i = 0 ; i < 10 ; i ++ ) {         map.put(i+"", i+"");     }     Iterator it = map.entrySet().iterator();     int i = 0;     while (it.hasNext()) {        if (i == 3) {            map.remove(3+"");        }        Entry entry = it.next();        System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());           i++;     } }

该段代码定义了一个hashmap对象并存放了10个键值对,在迭代遍历过程中,使用map的remove方法移除了一个元素,导致抛出了ConcurrentModificationException异常:

2、多线程环境下:

public class FailFastTest {      public static List list = new ArrayList();        private static class MyThread1 extends Thread {            @Override            public void run() {                 Iterator iterator = list.iterator();                 while(iterator.hasNext()) {                      String s = iterator.next();                      System.out.println(this.getName() + ":" + s);                      try {                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 }                 super.run();            }      }        private static class MyThread2 extends Thread {            int i = 0;            @Override            public void run() {                 while (i < 10) {                      System.out.println("thread2:" + i);                      if (i == 2) {                         list.remove(i);                      }                      try {                     Thread.sleep(1000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                      i ++;                 }            }      }        public static void main(String[] args) {            for(int i = 0 ; i < 10;i++){             list.add(i+"");         }            MyThread1 thread1 = new MyThread1();            MyThread2 thread2 = new MyThread2();            thread1.setName("thread1");            thread2.setName("thread2");            thread1.start();            thread2.start();      } }

启动两个线程,分别对其中一个对list进行迭代,另一个在线程1的迭代过程中去remove一个元素,结果也是抛出了java.util.ConcurrentModificationException

fail-fast的原理:

fail-fast是如何抛出ConcurrentModificationException异常的,又是在什么情况下才会抛出? 我们知道,对于集合如list,map类,我们都可以通过迭代器来遍历,而Iterator其实只是一个接口,具体的实现还是要看具体的集合类中的内部类去实现Iterator并实现相关方法。这里我们就以ArrayList类为例。在ArrayList中,当调用list.iterator()时,其源码是: 

public Iterator iterator() {         return new Itr(); }

即它会返回一个新的Itr类,而Itr类是ArrayList的内部类,实现了Iterator接口,下面是该类的源码:

    /**      * An optimized version of AbstractList.Itr      */     private class Itr implements Iterator {         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();             }         }           @Override         @SuppressWarnings("unchecked")         public void forEachRemaining(Consumer


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有