Skip to content

并发集合选型:从场景出发

先问自己两个问题

拿到一个并发需求,先问:

问题 1:需要什么数据结构?
  └─ Map  → ConcurrentHashMap
  └─ List → CopyOnWriteArrayList / ConcurrentLinkedQueue
  └─ Queue/Deque → ConcurrentLinkedQueue / BlockingQueue

问题 2:读写模式是什么?
  └─ 读多写少 → CopyOnWriteArrayList / CopyOnWriteArraySet
  └─ 读写均衡 → ConcurrentHashMap / ConcurrentLinkedQueue
  └─ 阻塞等待 → BlockingQueue(put/take)

Map 类型选择

场景推荐
高并发 MapConcurrentHashMap
高并发 + 排序 MapConcurrentSkipListMap
读多写少 MapConcurrentHashMap
偶尔并发Collections.synchronizedMap(new HashMap<>())
java
// 高并发
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

// 高并发 + 排序
ConcurrentSkipListMap<String, Integer> sorted = new ConcurrentSkipListMap<>();

List 类型选择

场景推荐
读多写少CopyOnWriteArrayList
高并发读写均衡ConcurrentLinkedQueue
偶尔并发Collections.synchronizedList(new ArrayList<>())
java
// 读多写少列表
CopyOnWriteArrayList<String> readHeavy = new CopyOnWriteArrayList<>();

// 高并发列表(作为队列使用)
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

Queue 类型选择

场景推荐
无界非阻塞队列ConcurrentLinkedQueue
有界阻塞队列LinkedBlockingQueue
同步队列(一个元素)SynchronousQueue
优先级队列PriorityBlockingQueue
延迟队列DelayQueue
java
// 无界非阻塞队列(CAS 实现)
ConcurrentLinkedQueue<Task> tasks = new ConcurrentLinkedQueue<>();

// 有界阻塞队列(生产者-消费者)
BlockingQueue<Task> bounded = new LinkedBlockingQueue<>(100);

// 同步队列(put 必须等待 take)
SynchronousQueue<Object> sync = new SynchronousQueue<>();

Set 类型选择

场景推荐
高并发 SetConcurrentHashMap.newKeySet()
读多写少 SetCopyOnWriteArraySet
高并发 + 排序 SetConcurrentSkipListSet
java
// 高并发 Set
Set<String> set = ConcurrentHashMap.<String>newKeySet();

// 读多写少 Set
CopyOnWriteArraySet<String> readSet = new CopyOnWriteArraySet<>();

选型决策树

数据结构是什么?

├── Map
│   ├── 高并发 → ConcurrentHashMap
│   └── 高并发 + 排序 → ConcurrentSkipListMap

├── List
│   ├── 读多写少 → CopyOnWriteArrayList
│   └── 读写均衡 → ConcurrentLinkedQueue

├── Queue
│   ├── 非阻塞 → ConcurrentLinkedQueue
│   └── 阻塞 → BlockingQueue(按需求选择)
│       ├── 有界 → LinkedBlockingQueue
│       ├── 优先级 → PriorityBlockingQueue
│       └── 延迟 → DelayQueue

└── Set
    ├── 高并发 → ConcurrentHashMap.newKeySet()
    ├── 读多写少 → CopyOnWriteArraySet
    └── 高并发 + 排序 → ConcurrentSkipListSet

性能对比

集合读性能写性能迭代安全
ConcurrentHashMap极快(无锁)快(CAS)Fail-Safe
CopyOnWriteArrayList极快(无锁)慢(复制)Fail-Safe
ConcurrentLinkedQueue快(CAS)Fail-Safe
Collections.synchronizedList慢(锁)慢(锁)Fail-Fast

常见误区

误区 1:用 CopyOnWriteArrayList 做高并发列表

java
// ❌ CopyOnWriteArrayList 写操作复制全量数组
// 1000 次写入 = 复制 1000 次整个数组!
CopyOnWriteArrayList<String> cow = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10000; i++) {
    cow.add("item" + i); // 极慢
}

// ✅ 写多场景用 ConcurrentLinkedQueue
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();

误区 2:用 BlockingQueue 做非阻塞队列

java
// ❌ BlockingQueue 的 add/put 有阻塞语义
BlockingQueue<Task> q = new LinkedBlockingQueue<>();
q.add(task); // 队列满时抛异常

// ✅ 非阻塞用 ConcurrentLinkedQueue
ConcurrentLinkedQueue<Task> queue = new ConcurrentLinkedQueue<>();
queue.offer(task); // 非阻塞

总结

需求推荐
高并发 MapConcurrentHashMap
高并发 + 排序 MapConcurrentSkipListMap
读多写少 ListCopyOnWriteArrayList
高并发 List/QueueConcurrentLinkedQueue
生产者-消费者BlockingQueue
高并发 SetConcurrentHashMap.newKeySet()

一句话:并发集合选型看两个维度——数据结构和读写模式。


相关链接

基于 VitePress 构建