java中线程安全集合与非线程安全集合不能直接转换;可通过collections.synchronizedxxx()包装或java.util.concurrent并发集合替代,但需注意迭代同步、避免假同步,并优先使用内置原子方法。

Java 中线程安全集合类与非线程安全类之间**不能直接“转换”**,因为它们是不同实现、不同设计目标的类,不存在类型强制转换或一键切换机制。所谓“转换”,实际是指在多线程场景下,如何安全地使用非线程安全集合(如 ArrayList、HashMap),或如何替代/包装它们以获得线程安全性。
用 Collections.synchronizedXxx() 包装非线程安全集合
这是最轻量的“模拟线程安全”的方式,适用于读多写少、且调用方能保证迭代时手动同步的场景:
-
Collections.synchronizedList(new ArrayList())→ 返回List接口,底层仍是ArrayList,但所有 public 方法加了synchronized - 同理有
synchronizedMap、synchronizedSet等 -
注意:迭代仍需手动同步,否则可能抛
ConcurrentModificationException或看到不一致状态
错误写法:for (String s : syncList) { ... }
正确写法:synchronized(syncList) { for (String s : syncList) { ... } }
用并发包(java.util.concurrent)替代原生集合
这是更推荐的“升级”方式,不是包装,而是选用专为并发设计的高性能实现:
- 代替
ArrayList→CopyOnWriteArrayList(适合读极多、写极少,如监听器列表) - 代替
HashMap→ConcurrentHashMap(支持高并发读写,分段锁 / CAS + synchronized 优化) - 代替
HashSet→ConcurrentHashMap.newKeySet()或CopyOnWriteArraySet - 代替
LinkedList(队列用途)→ConcurrentLinkedQueue或BlockingQueue子类(如ArrayBlockingQueue)
避免“假转换”:别用 synchronized 块临时包裹非安全集合
有人试图这样“变安全”:
List<string> list = new ArrayList();
synchronized(list) {
list.add("a");
list.remove("b");
}</string>
这不是线程安全集合,只是单次操作加锁。其他线程仍可绕过锁直接调用 list.add(),导致数据错乱。真正的线程安全必须控制全部访问入口,要么用包装类,要么换并发集合,要么封装成私有成员并严格管控方法暴露。
自定义线程安全包装器(进阶)
若标准类不满足需求(如需要复合操作原子性),可封装:
- 把
HashMap封进一个类,所有方法加synchronized,并提供putIfAbsentAndCompute()这类原子组合操作 - 使用
ReentrantLock替代synchronized,支持可中断、超时、公平性等 - 注意:自己实现易出错,优先考虑
ConcurrentHashMap.computeIfAbsent()等内置原子方法
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











