
线程安全的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
mikechen睿哥,10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。