Java 并发集合

并发集合解决什么、不解决什么:ConcurrentHashMap、阻塞队列与写时复制结构的选型。

#type / concept #status / growing #tech / dev #resource / java

[!info] 关联笔记

Java 并发集合

这个概念为什么出现

普通 HashMap/ArrayList 非线程安全。并发集合在特定操作上提供线程安全与更好伸缩,但并不自动保证多步业务不变量

[!abstract] 一句话理解 并发集合让单次 API 调用在并发下安全;复合“先查后改”仍需原子方法(如 compute)或外部同步。

最小可运行示例

场景:多线程统计接口命中次数

import java.util.concurrent.ConcurrentHashMap;

public class HitCounter {
    private final ConcurrentHashMap<String, Integer> hits = new ConcurrentHashMap<>();

    void hit(String path) {
        hits.merge(path, 1, Integer::sum); // 原子复合更新
    }

    int get(String path) {
        return hits.getOrDefault(path, 0);
    }

    public static void main(String[] args) throws Exception {
        HitCounter c = new HitCounter();
        Thread t1 = new Thread(() -> { for (int i=0;i<1000;i++) c.hit("/a"); });
        Thread t2 = new Thread(() -> { for (int i=0;i<1000;i++) c.hit("/a"); });
        t1.start(); t2.start(); t1.join(); t2.join();
        System.out.println(c.get("/a"));
    }
}

建议运行:

javac HitCounter.java && java HitCounter

期望输出:

2000

结合场景再看三个关注点

  1. merge/compute 而不是 get+put
  2. 迭代弱一致,不保证强快照。
  3. BlockingQueue 适合作生产者-消费者通道。

核心概念与准确模型

1. ConcurrentHashMap

  • 分段/桶级并发(实现演进)
  • 禁止 null 键值(与 HashMap 不同)

2. BlockingQueue

  • put/take 阻塞
  • 线程池工作队列常用

3. CopyOnWriteArrayList

  • 读多写少
  • 写拷贝成本高

边界情况与反直觉行为

  1. size 等在并发下是估算/瞬时。
  2. 复合业务校验库存仍要领域层原子性/DB 约束。
  3. 并发集合 ≠ 免锁设计完成。

常见误区

[!warning] 常见误区:ConcurrentHashMap 包治百病 它不替代事务与跨键不变量。

工程实践

  1. 优先原子复合 API。
  2. 队列设定容量实现背压。
  3. 读多写少结构先测量。
  4. 与数据库约束一起设计正确性。

本节总结

  • 并发容器保单操作安全
  • 复合操作要用原子 API
  • 选型看读写模式

自测题

  1. 为什么 CHM 不支持 null?
  2. BlockingQueue 如何形成背压?
参考答案
  1. null 与“不存在”语义混淆,并发下更难解释。
  2. 有界队列满时 put 阻塞/拒绝,减缓生产者。

延伸阅读与资料来源

资料类型支撑内容
ConcurrentHashMapAPI语义
BlockingQueueAPI阻塞队列
创建于 2026/7/15 更新于 2026/7/15