线程安全的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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》