Java并发面试题 - Java线程安全的集合有哪些?
一、线程安全集合概述
在Java多线程编程中,当多个线程同时访问和修改同一个集合时,可能会引发数据不一致的问题。为了解决这个问题,Java提供了多种线程安全的集合实现。
二、传统线程安全集合
1. Vector和Hashtable
Java早期提供的线程安全集合,通过synchronized
关键字实现同步。
Vector<String> vector = new Vector<>();
vector.add("item1");
vector.add("item2");
Hashtable<Integer, String> hashtable = new Hashtable<>();
hashtable.put(1, "value1");
2. Collections工具类包装的集合
通过Collections.synchronizedXXX()
方法可以将非线程安全集合包装成线程安全版本。
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<Integer, String> syncMap = Collections.synchronizedMap(new HashMap<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
三、JUC并发集合
Java 5引入了java.util.concurrent
包,提供了更高效的并发集合实现。
1. CopyOnWriteArrayList
写时复制的List实现,适合读多写少的场景。
CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
cowList.add("item1");
String item = cowList.get(0);
2. ConcurrentHashMap
高并发的HashMap实现,采用分段锁技术(Java 7)或CAS+synchronized(Java 8+)。
ConcurrentHashMap<Integer, String> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put(1, "value1");
String value = concurrentMap.get(1);
3. ConcurrentLinkedQueue
基于链接节点的无界线程安全队列,采用CAS实现。
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("item1");
String item = queue.poll();
4. BlockingQueue接口实现
阻塞队列,常用于生产者-消费者模式。
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10);
// 生产者
blockingQueue.put("item1");
// 消费者
String item = blockingQueue.take();
四、线程安全集合对比
集合类型 | 实现方式 | 适用场景 | 特点 |
---|---|---|---|
Vector/Hashtable | 方法级synchronized | 遗留系统 | 全表锁,性能差 |
Collections.synchronizedXXX | 方法级synchronized | 简单同步需求 | 包装器模式,性能一般 |
CopyOnWriteArrayList | 写时复制 | 读多写少 | 读无锁,写复制开销大 |
ConcurrentHashMap | 分段锁/CAS | 高并发Map | 并发度高,性能好 |
ConcurrentLinkedQueue | CAS | 高并发队列 | 无锁,非阻塞 |
BlockingQueue | 锁+条件变量 | 生产者-消费者 | 阻塞操作,容量控制 |
五、选择建议
- 读多写少:考虑
CopyOnWriteArrayList
- 高并发Map:优先选择
ConcurrentHashMap
- 生产者-消费者:使用
BlockingQueue
实现类 - 简单同步:可以使用
Collections.synchronizedXXX
包装 - 避免使用:
Vector
和Hashtable
(遗留类)
六、总结
Java提供了丰富的线程安全集合选择,从早期的synchronized
集合到现代的并发集合,开发者应根据具体场景选择最合适的实现。理解各种线程安全集合的内部实现机制,有助于编写出更高效、更可靠的多线程程序。