1. 程式人生 > 實用技巧 >java集合併發操作異常解決方法:CopyOnWriteArrayList

java集合併發操作異常解決方法:CopyOnWriteArrayList

一、我們知道ArrayList是執行緒不安全的,請編寫一個不安全的案例並給出解決方案

HashSet與ArrayList一致 HashMap

HashSet底層是一個HashMap,儲存的值放在HashMap的key裡,value儲存了一個PRESENT的靜態Object物件

1、執行緒不安全

package com.jian8.juc.collection;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 集合類不安全問題
 * ArrayList
 */
public class ContainerNotSafeDemo {
    public static void main(String[] args) {
        notSafe();
    }

    /**
     * 故障現象
     * java.util.ConcurrentModificationException
     */
    public static void notSafe() {
        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(list);
            }, "Thread " + i).start();
        }
    }
}

報錯:

Exception in thread "Thread 10" java.util.ConcurrentModificationException

2、導致原因

併發正常修改導致

一個人正在寫入,另一個同學來搶奪,導致資料不一致,併發修改異常

3、解決方法:**CopyOnWriteArrayList

List<String> list = new Vector<>();//Vector執行緒安全
List<String> list = Collections.synchronizedList(new ArrayList<>());//使用輔助類
List<String> list = new CopyOnWriteArrayList<>();//寫時複製,讀寫分離
Map<String, String> map = new ConcurrentHashMap<>(); Map<String, String> map = Collections.synchronizedMap(new HashMap<>());

CopyOnWriteArrayList.add方法:

CopyOnWrite容器即寫時複製,往一個元素新增容器的時候,不直接往當前容器Object[]新增,而是先將當前容器Object[]進行copy,複製出一個新的容器Object[] newElements,讓後新的容器新增元素,新增完元素之後,再將原容器的引用指向新的容器setArray(newElements),這樣做可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因為當前容器不會新增任何元素,所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器

	public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }