1. 程式人生 > 其它 >Java JUC併發之集合類不安全問題

Java JUC併發之集合類不安全問題

六、集合類不安全

List 不安全

package com.liu.unsafeListOrSet;

import com.liu.pc.A;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

// java.util.ConcurrentModificationException 併發修改異常
public class ListTest {
    public static void main(String[] args) {
        // 單執行緒下非常安全
        //List<String> list = Arrays.asList("1", "2", "3");
        //list.forEach(System.out::println);

        // 併發下的ArrayList 不安全的
        /**
         * 解決方案:
         * 1. List<String> list = new Vector<>();
         * 2. List<String> list2 = Collections.synchronizedList(new ArrayList<>());
         * 3. List<String> list3 = new CopyOnWriteArrayList<>();
         */

        // List<String> list = new ArrayList<>();
        // List<String> list1 = new Vector<>();
        // List<String> list2 = Collections.synchronizedList(new ArrayList<>());
        // List<String> list3 = new CopyOnWriteArrayList<>();

        // CopyOnWrite 寫入時複製  COW 計算機程式設計領域的一種優化策略
        // 多個執行緒呼叫的時候 list 讀取的時候 => 固定 寫入(覆蓋)
        // 在寫入的時候避免覆蓋,造成資料問題! 寫入時複製

        // 讀寫分離
        // CopyOnWrite(Lock) vs Vector (Synchronized) ? 好在哪裡? 效率方面
        List<String> list3 = new CopyOnWriteArrayList<>();

        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                // UUID 通用唯一識別碼
                list3.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(list3);
            },String.valueOf(i)).start();
        }
    }
}

Collections 類: 對集合進行操作的包裝器

Collection.synchronizedList: 返回一個同步(執行緒安全)的List

Set不安全

package com.liu.unsafeListOrSet;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;

// Set 同樣不安全 : java.util.ConcurrentModificationException 併發修改異常

/**
 * 解決方案
 * 1. Set<String> set = Collections.synchronizedSet(new HashSet<>()); // 使用Collections
 * 2. Set<String> set = new CopyOnWriteArraySet<>(); // 使用CopyOnWriteSet
 */
public class SetTest {
    public static void main(String[] args) {

        // Set<String> set = new HashSet<>();
        // Set<String> set = Collections.synchronizedSet(new HashSet<>()); // 使用Collections
        Set<String> set = new CopyOnWriteArraySet<>(); // 使用CopyOnWriteSet
        for (int i = 1; i <= 3000; i++) {
            new Thread(()->{
                set.add(UUID.randomUUID().toString().substring(0, 5));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

HahSet 底層原始碼是什麼?

本質: HashMap

    public HashSet() {
        map = new HashMap<>();
    }

add() Set 本質就是map, key是無法重複的

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

private static final Object PRESENT = new Object(); // 不變的值

IO、 集合、 常用類

Map 不安全

HashMap: 載入因子 LoadFactor、初始容量 InitialCapacity

HashMap 的 put():

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
package com.liu.unsafeListOrSet;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class MapTest {

    // java.util.ConcurrentModificationException 併發修改異常

    /**
     * 解決方案
     * 1. Collections
     * 2. new ConcurrentHashMap();
     * @param args
     */
    public static void main(String[] args) {

        // Map是這樣用的嗎?  不是 工作中不用HashMap
        // 預設等價於什麼? new HashMap<>(16,0.75);
        // 載入因子 LoadFactor、 初始化容量 initialCapacity

        // Map<String, String> map = new HashMap<>();
        // Map<String, String> map = Collections.synchronizedMap(new HashMap<>());

         Map<String, String> map = new ConcurrentHashMap<>(); // 併發的HashMap

        for (int i = 0; i < 30; i++) {

            new Thread(()->{
                map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

ConcurrentHashMap 原理 完全的併發性 + 高預期併發性 的 雜湊表

本文來自部落格園,作者:{夕立君},轉載請註明原文連結:https://www.cnblogs.com/liuzhhhao/p/15016338.html