CopyOnWriteArrayList 是什麼?

本文內容如有錯誤、不足之處,歡迎技術愛好者們一同探討,在本文下面討論區留言,感謝。

簡述

Java 中的 CopyOnWriteArrayListList 接口的線程安全實現。在 Java 1.5Collections 框架的一部分中添加了 CopyOnWriteArrayList。在多線程程序中,當開發人員希望以線程安全的方式遍歷列表而無需顯式同步時,CopyOnWriteArrayList 非常有用。

它是ArrayList的增強版本,其中所有修改(添加,更新,刪除等)都通過創建新副本來實現。

繼承關係

下圖是它的實現關係圖:
在這裏插入圖片描述

功能

  • CopyOnWriteArrayList 類實現List並繼承 RandomAccess 接口,因此提供 ArrayList 類中可用的所有功能。
  • 使用 CopyOnWriteArrayList 進行更新操作的成本很高,因爲每個迭代器都會創建基礎數組的克隆副本,併爲其添加/更新元素。
  • 它是 ArrayList 的線程安全版本。每個訪問列表的線程在初始化此列表的迭代器時都會看到自己創建的快照版本。
  • 因爲它在創建迭代器時獲取基礎數組的快照,所以它不會拋出 ConcurrentModificationException
  • 不支持對迭代器的操作(刪除,更新和添加),執行這些方法將拋出 UnsupportedOperationException
  • CopyOnWriteArrayList 是同步List的併發替代,當迭代的次數超過一定次數時,CopyOnWriteArrayList 可以提供更好的併發性。
  • 它允許重複的元素和異構對象(使用泛型來獲取編譯時錯誤)。
  • 因爲它每次創建迭代器時都會創建一個新的數組副本,所以性能比ArrayList 慢。

示例

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 *
 * Java program to demonstrate What is CopyOnWriteArrayList in Java,
 *  CopyOnWriteArrayList 的 Iterator 不支持添加,刪除,修改操作。
 */
public class CopyOnWriteArrayListExample{

    public static void main(String args[]) {
     
        CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<String>();
        threadSafeList.add("Java");
        threadSafeList.add("J2EE");
        threadSafeList.add("Collection");
     
        //add, remove operator 不被 CopyOnWriteArrayList iterator 支持
        Iterator<String> failSafeIterator = threadSafeList.iterator();
        while(failSafeIterator.hasNext()){
            System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
            // failSafeIterator.remove(); //不支持的操作,拋出 java.lang.UnsupportedOperationException 異常信息棧。
        }
    }
}

輸出結果:

Read from CopyOnWriteArrayList : Java
Read from CopyOnWriteArrayList : J2EE
Read from CopyOnWriteArrayList : Collection

插入時迭代

假設我們正在創建一個存儲整數的 CopyOnWriteArrayList 實例:

CopyOnWriteArrayList<Integer> numbers  = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 8});

接下來,我們要遍歷該數組,因此我們要創建一個 Iterator 實例:

Iterator<Integer> iterator = numbers.iterator();

創建迭代器後,將一個新元素添加到數字列表中:

numbers.add(10);

請記住,當爲 CopyOnWriteArrayList 創建迭代器時,在調用 iterator() 時,將獲得列表中數據的不可變快照。

因此,在進行迭代時,我們不會在迭代中看到數字10:

List<Integer> result = new LinkedList<>();
iterator.forEachRemaining(result::add);
  
assertThat(result).containsOnly(1, 3, 5, 8);

使用新創建的Iterator進行的後續迭代還將返回添加的數字10:

Iterator<Integer> iterator2 = numbers.iterator();
List<Integer> result2 = new LinkedList<>();
iterator2.forEachRemaining(result2::add);
 
assertThat(result2).containsOnly(1, 3, 5, 8, 10);

以線程安全的方式對其進行迭代,而其他線程可以繼續從中插入或刪除元素。


import java.util.concurrent.CopyOnWriteArrayList; 
import java.util.*; 
  
class ConcurrentDemo extends Thread { 
  
    static CopyOnWriteArrayList l = new CopyOnWriteArrayList(); 
  
    public void run() 
    { 
        // 子線程添加一個元素到集合中
        l.add("D"); 
    } 
  
    public static void main(String[] args) 
        throws InterruptedException 
    { 
        l.add("A"); 
        l.add("B"); 
        l.add("c"); 
  
        // 創建一個子線程進行操作
        ConcurrentDemo t = new ConcurrentDemo();
        // 直接調用資源類中的run方法 
        t.run(); 
  
        Thread.sleep(1000); 
  
        // 獲得集合中的例子
        Iterator itr = l.iterator(); 
        while (itr.hasNext()) { 
            String s = (String)itr.next(); 
            System.out.println(s); 
            Thread.sleep(1000); 
        } 
        System.out.println(l); 
    } 
} 

結語

簡而言之,如果您主要需要遍歷列表而不進行修改,使用 CopyOnWriteArrayList

參考資料

CopyOnWriteArrayList in java(Java中的CopyOnWriteArrayList

Guide to CopyOnWriteArrayList(CopyOnWriteArrayList指南

What is CopyOnWriteArrayList in Java - Example Tutorial(什麼是Java中的CopyOnWriteArrayList-示例教程

CopyOnWriteArrayList in java(Java中的CopyOnWriteArrayList

Java CopyOnWriteArrayList class(Java CopyOnWriteArrayList類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章