程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> java fail-fast 機制探究,javafail-fast

java fail-fast 機制探究,javafail-fast

編輯:JAVA綜合教程

java fail-fast 機制探究,javafail-fast


什麼是 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 就不足為其了!

看似簡單的問題多想一點就好了!

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved