加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

java fail-fast 机制探究

发布时间:2016-10-28 17:55:11 所属栏目:教程 来源:站长网
导读:什么是 fail-fast 机制? fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。 fail-fast会在以下两种情况下抛出ConcurrentModificationException (1)单线程环境 集合被创建后,在遍历它的过程中修改了结构。

什么是 fail-fast 机制?

fail-fast机制在遍历一个集合时,当集合结构被修改,会抛出Concurrent Modification Exception。 fail-fast会在以下两种情况下抛出ConcurrentModificationException

(1)单线程环境 集合被创建后,在遍历它的过程中修改了结构。  

  注意 remove()方法会让expectModcount和modcount 相等,所以是不会抛出这个异常。

(2)多线程环境 当一个线程在遍历这个集合,而另一个线程对这个集合的结构进行了修改。

如下:

private static void test0() {

        List<String> list = new ArrayList<>();
        list.add("a1");
        list.add("a2");
        list.add("a3");
        list.add("a4");
        list.add("a5");
        list.add("a6");
        list.add("a7");
        list.add("a8");

        for (String s : list) {
            list.remove(s);
        }

        System.out.println(list);

    }

 

运行会抛出异常

java.util.ConcurrentModificationException

如果又想在遍历的时候做删除操作呢? 借肋iterator,,如下:

private static void test1() {

        List<String> list = new ArrayList<>();
        list.add("a1");
        list.add("a2");
        list.add("a3");
        list.add("a4");
        list.add("a5");
        list.add("a6");
        list.add("a7");
        list.add("a8");

        Iterator<String> iter = list.iterator();
        while (iter.hasNext()) {
            String str = iter.next();
            System.out.println(str);

            //iter.remove();
            if (Randoms.random(1, 9) % 2 == 0) {
                iter.remove();
            }
        }

        System.out.println(list);

    }

 

这里我们并没有用list.remove元素而是iter.reomve,但实际list中的元素已经被删除也没有抛异常,为什么会这样?

调试的时候我们发现iter.reomve执行最终调用的是 ArrayList

public E remove(int index)

所以自然影响了原来的集合。

Iterator被创建之后会建立一个指向原来对象的单链索引表, 当list删除元素里不会影响索引,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

我们再看段代码:

 

private static void test2() {
 List list2 = Arrays.asList(new String[]{"a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8",});

Iterator iter2 = list2.iterator(); 

while (iter2.hasNext()) { 
      String str = iter2.next(); System.out.println(str);

        //iter.remove();
        if (Randoms.random(1, 9) % 2 == 0) {
            iter2.remove();
        }
    }

    System.out.println(list2);
}

 

结果:

会抛出异常java.lang.UnsupportedOperationException

为什么呢?感觉跟test1是一样的?

我们查看源码Arrays:

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable{...}

 

发现两个ArrayList并不是同一个类却取了同一个名字:

java.util.Arrays.ArrayList!=java.util.ArrayList

你还是你同一个名字却是另一个他....

java.util.Arrays.ArrayList并没有实现remove方法,所以也就抛出了UnsupportedOperationException 就不足为其了!

看似简单的问题多想一点就好了!

 

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读