fail | 您所在的位置:网站首页 › java集合的作用是什么和什么的区别 › fail |
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 实验室设备网 版权所有 |