首頁 >Java >java教程 >Java JUC怎麼操作List安全類別的集合

Java JUC怎麼操作List安全類別的集合

WBOY
WBOY轉載
2023-04-30 09:10:06757瀏覽

不安全的集合

在單執行緒應用中,通常會採取new ArrayList(),指定一個List集合,用來存放可重複的資料。

但在多執行緒下,往往會出現意想不到的問題,程式碼如下所示:

import java.util.*;
public class ListTest {
    public static void main(String[] args) throws InterruptedException {
        // 创建list集合
        //List<String> lists = Arrays.asList("1", "2", "3");
        // 不安全
        List<String> lists = new ArrayList<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
            new Thread(()->{
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

多執行緒操作同一集合物件訊息,往往會出現java.util.ConcurrentModificationException異常報錯資訊.

Java中提供的安全措施

在java語言中,提供了一個新的List集合,java.util.Vector類,具體看下列程式碼:

import java.util.*;
public class ListTest {
    public static void main(String[] args) throws InterruptedException {
        // 创建list集合
        //List<String> lists = Arrays.asList("1", "2", "3");
        // 不安全
        //List<String> lists = new ArrayList<>();
		List<String> lists = new Vector<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
            new Thread(()->{
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

不會出現java.util.ConcurrentModificationException報錯訊息。

為什麼能保證資料的安全操作?

Java JUC怎么操作List安全类的集合

採取了 synchronized 針對方法執行呼叫者加鎖,保證add操作的多執行緒安全性!

JUC下的安全List集合

在JUC套件下,提供以下幾種建立安全集合的方式。

  • 方式一:Collections.synchronizedList(new ArrayList<>());

import java.util.*;
public class ListTest {
    public static void main(String[] args) throws InterruptedException {
		List<String> lists = Collections.synchronizedList(new ArrayList<>());

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
            new Thread(()->{
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

查看底層原始碼實作邏輯

Java JUC怎么操作List安全类的集合

#判斷傳入的list 集合類型,判斷類型是否為java.util.RandomAccess,如果是則採取java.util.Collections.SynchronizedRandomAccessList建構集合,如果不是則採取java.util.Collections.SynchronizedList建構集合。

源碼中對應的add操作邏輯如下所示:

Java JUC怎么操作List安全类的集合

#採取synchronized同步程式碼區塊的方式,資料的add操作實現加鎖!

  • 方式二:new CopyOnWriteArrayList();

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListTest {
    public static void main(String[] args) throws InterruptedException {
        List<String> lists = new CopyOnWriteArrayList<>();

        // 开启十个线程增加数据
        for (int i = 1; i <= 40; i++) {
            new Thread(()->{
                lists.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+lists);
            },String.valueOf(i)).start();
        }
    }
}

原始碼中的介紹如下:

Java JUC怎么操作List安全类的集合

Java JUC怎么操作List安全类的集合

#顯而易見,其邏輯如下所示:

  1. #呼叫add方法後,拿到java.util.concurrent.locks .ReentrantLock物件資訊。

  2. 呼叫 lock.lock() 拿到鎖定!

  3. 將原數組物件copy操作,並建立原始數組大小 1的新數組。

  4. 將新資料放入新陣列中。

  5. 任何操作finally,都進行鎖定的釋放!

效能方面

JUC套件下的Lock操作,都比synchronized效能更好!

以上是Java JUC怎麼操作List安全類別的集合的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除