最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程高并發(fā)中解決ArrayList與HashSet和HashMap不安全的方案

 更新時(shí)間:2021年11月16日 11:06:07   作者:張起靈-小哥  
ArrayList實(shí)現(xiàn)了可變大小的數(shù)組。它允許所有元素,包括null。ArrayList沒(méi)有同步,HashMap和Hashtable類似,不同之處在于HashMap是非同步的,并且允許null,關(guān)于HashSet有一件事應(yīng)該牢記,即就條目數(shù)和容量之和來(lái)講,迭代是線性的,接下來(lái)讓我們?cè)敿?xì)來(lái)了解吧

1.ArrayList的線程不安全解決方案

將main方法的第一行注釋打開(kāi),多執(zhí)行幾次,會(huì)看到如下圖這樣的異常信息:👇👇👇

這是一個(gè) 并發(fā)修改 異常,首先ArrayList肯定是線程不安全的,產(chǎn)生這個(gè)異常的原因就是可能第一個(gè)線程剛進(jìn)入 ArrayList 集合中要進(jìn)行 add 操作時(shí),另外一個(gè)線程此時(shí)也進(jìn)來(lái)進(jìn)行 add 操作,而第三個(gè)線程又進(jìn)來(lái)進(jìn)行 get 操作,導(dǎo)致讀寫沒(méi)辦法進(jìn)行同步了,最終打印結(jié)果的時(shí)候就炸了。

解決方案看代碼中的剩下幾行注釋。

package test.notsafe;
 
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
 
/**
 * 演示ArrayList的線程不安全問(wèn)題及解決方案
 */
public class ThreadDemo2 {
    public static void main(String[] args) {
        //List<String> list = new ArrayList<>();
 
        //解決方法1:使用Vector
        //List<String> list = new Vector<>();
 
        //解決方法2:Collections
        //List<String> list = Collections.synchronizedList(new ArrayList<>());
 
        //解決方法3:CopyOnWriteArrayList
        List<String> list = new CopyOnWriteArrayList<>();
 
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

關(guān)于 CopyOnWriteArrayList 解決線程不安全問(wèn)題的簡(jiǎn)單解釋:就看源碼中的 add(E e) 這個(gè)方法:

    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();
        }
    }

這個(gè) CopyOnWriteArrayList 在進(jìn)行 add 添加操作之前,先進(jìn)行 lock 上鎖,然后通過(guò) getArray() 獲取到原 ArrayList 集合容器,之后調(diào)用 Arrays.copyOf 方法將原容器拷貝出一個(gè)新容器,因?yàn)橐砑樱ㄩL(zhǎng)度自然也要 +1),之后向這個(gè)新容器中添加元素,添加完成之后,調(diào)用 setArray 方法將原容器的引用指向了這個(gè)新的容器。 那么這樣做的好處就是:添加元素在新容器中,原容器該是啥樣還是啥樣,其他線程要get讀取元素就還從原容器中讀(即多個(gè)線程可以進(jìn)行并發(fā)讀);而其他線程要 add 添加,要等待其他線程完成之后,將原容器的引用指向新容器就可以了。

CopyOnWrite 容器在面對(duì)讀和寫的時(shí)候是兩個(gè)不同的容器,也是用到了讀寫分離的思想。

2.HashSet的線程不安全解決方案

這里如果是 new HashSet 了話,仍然可能出現(xiàn)向上面 ArrayList 一樣的 并發(fā)修改異常。解決方案看代碼中的注釋。

package test.notsafe;
 
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
 
/**
 * 演示HashSet的線程不安全問(wèn)題及解決方案
 */
public class ThreadDemo3 {
    public static void main(String[] args) {
        //Set<String> set = new HashSet<>();
 
        //解決方法1:Collections
        //Set<String> set = Collections.synchronizedSet(new HashSet<>());
 
        //解決方法2:CopyOnWriteArraySet
        Set<String> set = new CopyOnWriteArraySet<>();
 
        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                set.add(UUID.randomUUID().toString().substring(0,8));
                System.out.println(set);
            },String.valueOf(i)).start();
        }
    }
}

3.HashMap的線程不安全解決方案

package test.notsafe;
 
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
 
/**
 * 演示HashMap的線程不安全問(wèn)題及解決方案
 */
public class ThreadDemo4 {
    public static void main(String[] args) {
        //Map<String,Object> map = new HashMap<>();
 
        //解決方法1:Collections
        //Map<String,Object> map = Collections.synchronizedMap(new HashMap<>());
 
        //解決方法2:ConcurrentHashMap
        Map<String,Object> map = new ConcurrentHashMap<>();
 
        for (int i = 0; i < 10; i++) {
            String key = String.valueOf(i);
            new Thread(() -> {
                map.put(key,UUID.randomUUID().toString().substring(0,8));
                System.out.println(map);
            },String.valueOf(i)).start();
        }
    }
}

到此這篇關(guān)于Java多線程高并發(fā)中解決ArrayList與HashSet和HashMap不安全的方案的文章就介紹到這了,更多相關(guān)Java 多線程高并發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

津南区| 南乐县| 南昌市| 自贡市| 沭阳县| 开阳县| 霍邱县| 海口市| 衡山县| 桑植县| 宁都县| 阜城县| 广饶县| 阳城县| 石台县| 城口县| 灵台县| 交口县| 五河县| 思茅市| 建德市| 福建省| 华坪县| 昭苏县| 克东县| 富阳市| 福鼎市| 丹阳市| 徐汇区| 隆回县| 昆明市| 大足县| 竹山县| 长垣县| 石屏县| 高碑店市| 达拉特旗| 昌平区| 崇明县| 阿坝| 磴口县|