如何根据并发量选择线程安全的集合类:Collections.synchronized vs JUC?
- 内容介绍
- 相关推荐
本文共计662个文字,预计阅读时间需要3分钟。
选择`Collections.synchronized`还是JUC并发集合,不能仅仅看有没有锁,关键要看实际并发量、读写比和操作类型。低并发、简单场景可以用`synchronized`包装器;中高并发、读多写少或需要原子复合操作时,JUC类更稳定、更高效。
低并发 + 简单读写:Collections.synchronized 足够
适合线程数少(比如 ≤ 5)、操作频次低(每秒增删查总和
- 单个 add、get、put 操作天然线程安全,无需额外同步
- 代码轻量,改造成本低,适合快速适配遗留逻辑
- 注意:遍历时必须显式加 synchronized 块,否则可能抛 ConcurrentModificationException
中高并发 + 读远多于写:优先 CopyOnWriteArrayList / CopyOnWriteArraySet
典型如监听器列表、配置项缓存、白名单集合等——读操作每秒成百上千,但写(增删)一天才几次。
- 读完全无锁,吞吐量高,迭代器绝对安全,不怕边读边改
- 写操作复制整个数组,内存开销和 GC 压力随集合大小线性增长,别用于 > 1000 元素且写较频繁的场景
- 不支持在迭代中修改,但也不需要你操心——它本来就返回快照
读写均衡 + 需要强一致性:ConcurrentHashMap 或 ConcurrentLinkedQueue 是主力
比如共享任务队列、实时计数器、会话状态映射表——读写都频繁,还常需要 putIfAbsent、computeIfPresent 这类原子语义。
- ConcurrentHashMap 的 get 几乎无锁,put 使用 CAS + 细粒度锁(JDK 8+),吞吐量通常是 synchronizedMap 的 3–10 倍
- size() 返回弱一致性结果,如需精确计数,建议配合 LongAdder 单独维护
- 不支持直接遍历修改(如 removeIf),应改用 computeXXX 或批量操作接口
需要阻塞协作或严格顺序:BlockingQueue 是标准解法
生产者-消费者模型、限流缓冲、消息管道等场景,核心诉求不是“快”,而是“等得到”和“不丢”。
- ArrayBlockingQueue(固定容量、可重入锁)适合资源确定、强调公平性的场景
- LinkedBlockingQueue(链表+双锁)吞吐更高,但 take/put 可能因扩容或 GC 引发短暂延迟
- 所有实现都保证了 offer/take 的线程安全与阻塞语义,无需手动加锁
本文共计662个文字,预计阅读时间需要3分钟。
选择`Collections.synchronized`还是JUC并发集合,不能仅仅看有没有锁,关键要看实际并发量、读写比和操作类型。低并发、简单场景可以用`synchronized`包装器;中高并发、读多写少或需要原子复合操作时,JUC类更稳定、更高效。
低并发 + 简单读写:Collections.synchronized 足够
适合线程数少(比如 ≤ 5)、操作频次低(每秒增删查总和
- 单个 add、get、put 操作天然线程安全,无需额外同步
- 代码轻量,改造成本低,适合快速适配遗留逻辑
- 注意:遍历时必须显式加 synchronized 块,否则可能抛 ConcurrentModificationException
中高并发 + 读远多于写:优先 CopyOnWriteArrayList / CopyOnWriteArraySet
典型如监听器列表、配置项缓存、白名单集合等——读操作每秒成百上千,但写(增删)一天才几次。
- 读完全无锁,吞吐量高,迭代器绝对安全,不怕边读边改
- 写操作复制整个数组,内存开销和 GC 压力随集合大小线性增长,别用于 > 1000 元素且写较频繁的场景
- 不支持在迭代中修改,但也不需要你操心——它本来就返回快照
读写均衡 + 需要强一致性:ConcurrentHashMap 或 ConcurrentLinkedQueue 是主力
比如共享任务队列、实时计数器、会话状态映射表——读写都频繁,还常需要 putIfAbsent、computeIfPresent 这类原子语义。
- ConcurrentHashMap 的 get 几乎无锁,put 使用 CAS + 细粒度锁(JDK 8+),吞吐量通常是 synchronizedMap 的 3–10 倍
- size() 返回弱一致性结果,如需精确计数,建议配合 LongAdder 单独维护
- 不支持直接遍历修改(如 removeIf),应改用 computeXXX 或批量操作接口
需要阻塞协作或严格顺序:BlockingQueue 是标准解法
生产者-消费者模型、限流缓冲、消息管道等场景,核心诉求不是“快”,而是“等得到”和“不丢”。
- ArrayBlockingQueue(固定容量、可重入锁)适合资源确定、强调公平性的场景
- LinkedBlockingQueue(链表+双锁)吞吐更高,但 take/put 可能因扩容或 GC 引发短暂延迟
- 所有实现都保证了 offer/take 的线程安全与阻塞语义,无需手动加锁

