3大线程安全的Set集合详解(建议收藏)

3大线程安全的Set集合详解(建议收藏)-mikechen

线程安全的Set集合有哪些?经常在Java面试被问到,下面就重点详解线程安全的Set集合,主要包含如下3个。

Collections.synchronizedSet

使用Colletcions这个工具类synchronized方法类,可以实现线程安全的Set集合。

如下所示:

Set<String> synSet = Collections.synchronizedSet(new HashSet<>());

这是一个使用Synchronized关键字实现线程安全的Set集合,使用该方法可以将任意Set集合转换为线程安全的Set集合。

但是由于使用了Synchronized关键字,可能会导致性能问题,因此不适合高并发场景。

 

ConcurrentHashMap.KeySetView

这是ConcurrentHashMap的一个内部类,它实现了Set接口,可以实现线程安全的Set集合。

如下所示:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConcurrentHashMapExample {

    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
        map.put("A", 1);
        map.put("B", 2);
        map.put("C", 3);

        ConcurrentHashMap.KeySetView<String, Integer> keySet = map.keySet();

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 创建3个线程,每个线程都对keySet进行操作
        for (int i = 0; i < 3; i++) {
            executorService.execute(() -> {
                for (String key : keySet) {
                    System.out.println(Thread.currentThread().getName() + " : " + key + " - " + map.get(key));
                }
            });
        }

        executorService.shutdown();
    }
}

该Set集合是基于ConcurrentHashMap实现的,因此它具有ConcurrentHashMap的高并发性能和线程安全性。

 

CopyOnWriteArraySet

CopyOnWriteArraySet是一个线程安全的Set集合,它使用了CopyOnWrite技术,可以实现线程安全的Set集合。

如下所示:

import java.util.concurrent.CopyOnWriteArraySet;

public class ThreadSafeSetExample {
    private CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();

    public void add(String item) {
        set.add(item);
    }

    public boolean contains(String item) {
        return set.contains(item);
    }

    public void remove(String item) {
        set.remove(item);
    }

    public int size() {
        return set.size();
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadSafeSetExample example = new ThreadSafeSetExample();

        // 创建并启动两个线程,每个线程都向集合中添加100个字符串
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                example.add("Thread 1 - " + i);
            }
        });

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                example.add("Thread 2 - " + i);
            }
        });

        thread1.start();
        thread2.start();

        // 等待两个线程执行完毕
        thread1.join();
        thread2.join();

        // 输出集合的大小,应该为200
        System.out.println("Set size: " + example.size());
    }
}

CopyOnWriteArraySet和CopyOnWriteArrayList实现原理一样,采用读写分离的并发策略,读操作的时候不加锁,写操作时创建底层数据的新副本。

CopyOnWriteArraySet即在修改集合时,会创建一个新的副本来修改,而不是直接修改原有集合,所以可以保证线程安全。

但是CopyOnWriteArraySet由于每次修改都需要创建新的副本,因此效率较低,适合读多写少的场景。

需要注意的是,虽然使用了线程安全的Set集合,但在实际使用中仍然需要正确地处理并发情况,例如使用同步机制或者使用CAS等方式来保证数据的一致性。

作者简介

陈睿|mikechen,10年+大厂架构经验,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法