java基礎理論學習筆記(3)——ArrayList等集合類不安全問題?解決方案:vector、Collections.sync工具類,或者JUC的CopyOnWriteArrList

ArrayList不是線程安全類,在多線程同時寫的情況下,會拋出java.util.ConcurrentModificationException異常。如下代碼,開啓30個線程同時對ArrayList進行寫操作,會報併發異常錯。

private static void listNotSafe() {
    List<String> list=new ArrayList<>();
    for (int i = 1; i <= 30; i++) {
        new Thread(() -> {
            list.add(UUID.randomUUID().toString().substring(0, 8));
            System.out.println(Thread.currentThread().getName() + "\t" + list);
        }, String.valueOf(i)).start();
    }
}

解決方法

  1. 使用VectorArrayList所有方法加synchronized,太重)。
  2. 使用Collections.synchronizedList()轉換成線程安全類。
  3. 使用java.concurrent.CopyOnWriteArrayList(推薦)

第一個方案中,vector源碼中可以看到,用上了synchronize修飾

而且他是在1.0就出來了;而ArrayList是1.2出來的,由於vector性能太差,後者是爲了解決這個問題而搞出來的,把併發問題交給其他方案去處理是更妥當的。

第二個方案中,可在jdk API中看到:

其中hashset的底層是hashmap實現的,他的value存儲的都是固定值。

HashSet底層是用HashMap實現的。既然是用HashMap實現的,那HashMap.put()需要傳兩個參數,而HashSet.add()傳一個參數,這是爲什麼?實際上HashSet.add()就是調用的HashMap.put(),只不過Value被寫死了,是一個private static final Object對象。

HashMap不是線程安全的,Hashtable是線程安全的,但是跟Vector類似,太重量級。所以也有類似CopyOnWriteMap,只不過叫ConcurrentHashMap

第三個方案中原理:

寫的時候必須對對象加鎖。

寫是在自己空間操作的,不影響併發讀,所以這是讀寫分離的。

List<String> list = new CopyOnWriteArrayList<>();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章