java并发集合通过分段锁、cas等机制提升高并发性能,需按读写比例和一致性需求选用concurrenthashmap、copyonwritearraylist或blockingqueue,并规避复合操作非原子性陷阱。

Java并发集合类通过更精细的锁粒度、无锁算法和分段设计,显著减少线程竞争,从而在高并发场景下比传统同步集合(如 Collections.synchronizedList 或 synchronizedMap)获得更高吞吐量。关键不是简单替换,而是理解每种并发集合的适用边界和使用习惯。
优先选用 ConcurrentHashMap 替代 synchronizedMap
ConcurrentHashMap 不是简单给整个 map 加锁,而是采用分段锁(JDK 7)或 CAS + synchronized(JDK 8+)策略,允许多个线程同时读、部分写操作并行。它支持高并发读(完全无锁)、安全的迭代(弱一致性快照),且不抛 ConcurrentModificationException。
- 避免用
putIfAbsent、computeIfAbsent等原子方法替代手动加锁判断——它们内部已保证线程安全 - 遍历时推荐用
entrySet().forEach(...)或forEach方法,而非显式Iterator;若需强一致性,应自行加锁或转为复制后处理 - 注意:
size()返回的是估算值(JDK 8+),高并发下可能滞后;如需精确计数,考虑用mappingCount()
用 CopyOnWriteArrayList 处理读多写少的列表场景
当列表极少修改(如配置监听器、事件处理器注册表),但遍历频繁时,CopyOnWriteArrayList 是理想选择。每次写操作复制底层数组,读操作全程无锁,避免了读写阻塞。
- 写操作开销大,不适合高频增删;尤其避免在循环中调用
add或remove - 迭代器基于创建时的快照,无法反映后续写入——这既是优点也是限制,需确认业务是否接受“读旧值”
- 不支持
ListIterator的双向修改;set(int, E)是线程安全的,但仍是复制数组
用 BlockingQueue 实现生产者-消费者解耦与流量控制
相比手动同步的 LinkedList + synchronized,ArrayBlockingQueue 或 LinkedBlockingQueue 提供阻塞/超时插入/获取、容量限制、公平性策略等能力,天然适配典型并发模型。
- 固定容量场景首选
ArrayBlockingQueue(内存可控、性能稳定);不确定长度或需动态扩容,选LinkedBlockingQueue(注意其默认容量为Integer.MAX_VALUE,可能掩盖背压问题) - 避免直接暴露队列引用给多个模块;建议封装成服务接口(如
submitTask(Runnable)),隐藏并发细节 - 慎用
poll()循环轮询;优先用take()或poll(long, TimeUnit)减少 CPU 空转
注意并发集合的“非原子复合操作”陷阱
单个方法(如 get、put)线程安全,但组合调用(如“检查再插入”)仍需额外同步。例如 map.get(key) == null && map.put(key, value) 并非原子操作。
- 用
computeIfAbsent替代手工检查+put:它保证整个逻辑只执行一次,且线程安全 - 对需要跨多个键/集合协同的逻辑(如转账:扣A账户+增B账户),并发集合本身无法保证事务性,必须引入外部锁(如
ReentrantLock)或更高层协调机制 - 不要假设
ConcurrentHashMap支持containsKey() + get()组合的安全性;应改用getOrDefault或computeIfPresent
不复杂但容易忽略:选对并发集合只是第一步,真正提升吞吐的关键在于匹配业务访问模式——读多?写多?是否需要强一致性?是否涉及复合逻辑?脱离场景谈“高性能”往往适得其反。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











