首頁 > 軟體

Java中ArrayList同步的2種方法分享

2022-03-17 19:02:26

前言:

        arrayList 的實現是預設不同步的。這意味著如果一個執行緒在結構上修改它並且多個執行緒同時存取它,它必須在外部同步。結構修改意味著從列表中新增或刪除元素或顯式調整後備陣列的大小。改變現有元素的值不是結構修改。

有兩種方法可以建立同步Arraylist:

  • 1. Collections.synchronizedList() 方法。
  • 2. 使用 CopyOnWriteArrayList。

方法1:使用 Collections.synchronizedList() 方法

        要進行序列存取,必須通過返回列表完成對後備列表的所有存取。

        在迭代返回的列表時,使用者必須手動同步它。因為在執行add()等方法的時候是加了synchronized關鍵字的,但是iterator()卻沒有加。所以在使用的時候需要加上synchronized

// Java program to demonstrate working of
// Collections.synchronizedList
import java.util.*;
 
class GFG
{
    public static void main (String[] args)
    {
        List<String> list =
        Collections.synchronizedList(new ArrayList<String>());
 
        list.add("practice");
        list.add("code");
        list.add("quiz");
 
        synchronized(list)
        {
            // must be in synchronized block
            Iterator it = list.iterator();
 
            while (it.hasNext())
                System.out.println(it.next());
        }
    }
}

方法 2:使用 CopyOnWriteArrayList

        ArrayList 的執行緒安全變體,其中所有可變操作(例如新增、設定、刪除...)都是通過建立底層陣列的單獨副本來實現的。它通過建立 List 的單獨副本來實現執行緒安全,這與 vector 或其他集合用於提供執行緒安全的方式不同。

  • 當我們不能或不想同步遍歷,但需要防止並行執行緒之間的干擾時,它很有用。
  • 這是昂貴的,因為每次寫入操作都涉及單獨的陣列副本(例如新增,設定,刪除......)
  • 當你有List並且需要遍歷它的元素並且不經常修改它時,它是非常有效的。

        即使在建立迭代器後修改了 copyOnWriteArrayList,迭代器也不會丟擲ConcurrentModificationException,因為迭代器正在迭代 ArrayList 的單獨副本,而寫操作正在 ArrayList 的另一個副本上發生。

// Java program to illustrate the thread-safe ArrayList.
import java.io.*;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
 
class GFG
{
    public static void main (String[] args)
    {
        // creating a thread-safe Arraylist.
        CopyOnWriteArrayList<String> threadSafeList
            = new CopyOnWriteArrayList<String>();
 
        // Adding elements to synchronized ArrayList
        threadSafeList.add("geek");
        threadSafeList.add("code");
        threadSafeList.add("practice");
 
        System.out.println("Elements of synchronized ArrayList :");
 
        // Iterating on the synchronized ArrayList using iterator.
        Iterator<String> it = threadSafeList.iterator();
 
        while (it.hasNext())
            System.out.println(it.next());
    }
}

如果我們嘗試通過迭代器自己的方法修改 CopyOnWriteArrayList 會發生什麼?

        如果您嘗試通過迭代器自己的方法(例如 add()、set()、remove())修改CopyOnWriteArrayList,它會丟擲 UnsupportedOperationException 。

// Java program to illustrate the thread-safe ArrayList
import java.io.*;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;
 
class GFG
{
    public static void main (String[] args)
    {
        // creating a thread-safe Arraylist.
        CopyOnWriteArrayList<String> threadSafeList =
            new CopyOnWriteArrayList<String>();
 
        // Adding elements to synchronized ArrayList
        threadSafeList.add("geek");
        threadSafeList.add("code");
        threadSafeList.add("practice");
 
        System.out.println("Elements of synchronized ArrayList :");
 
        // Iterating on the synchronized ArrayList using iterator.
        Iterator<String> it = threadSafeList.iterator();
 
        while (it.hasNext())
        {
            String str = it.next();
            it.remove();
        }
    }
}

CopyOnWriteArrayList 的其他建構函式:

  • 1. CopyOnWriteArrayList(Collection<? extends E> c):建立一個包含指定集合元素的列表,按照集合迭代器返回的順序。
  • 2. CopyOnWriteArrayList(E[] toCopyIn):建立一個包含給定陣列副本的列表。

向量同步時為什麼要使用arrayList?

  • 效能: Vector 是同步和執行緒安全的,因此,它比 ArrayList 稍慢。
  • 功能: Vector 在每個單獨的操作級別進行同步。通常,程式設計師喜歡同步整個操作序列。同步單個操作既不安全又慢。
  • Vectors obsolete:向量被認為是過時的,並且在 java 中被非正式地棄用。此外,vector 對幾乎從未完成的每個單獨操作進行同步。大多數java程式設計師更喜歡使用ArrayList,因為如果他們需要進行同步,他們可能無論如何都會顯式地同步arrayList。

以下是 Java 中 ArrayList CopyOnWriteArrayList 類之間的顯著差異。

 陣列列表複製寫入陣列列表
同步ArrayList 不同步。CopyOnWriteArrayList 是同步的。
執行緒安全ArrayList 不是執行緒安全的。CopyOnWriteArrayList 是執行緒安全的。
迭代器型別ArrayList 迭代器是快速失敗的,如果在迭代過程中發生並行修改,則 ArrayList 會丟擲 ConcurrentModificationException。CopyOnWriteArrayList 是故障安全的,它在迭代過程中永遠不會丟擲 ConcurrentModificationException。其背後的原因是 CopyOnWriteArrayList 每次修改時都會建立一個新的陣列列表。
刪除操作ArrayList 迭代器支援在迭代過程中移除元素。如果在迭代期間嘗試刪除元素,則 CopyOnWriteArrayList.remove() 方法會引發異常。
表現ArrayList 更快。CopyOnWriteArrayList 比 ArrayList 慢。
從 Java 版本開始1.21.5

到此這篇關於Java中ArrayList同步的2種方法分享的文章就介紹到這了,更多相關Java中ArrayList同步內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com