ConcurrentHashMap 比 Hashtable 更快,因其分段锁(JDK7)或 CAS+synchronized 单节点锁(JDK8+),而 Hashtable 全表同步;CopyOnWriteArrayList 适合读多写少、允许最终一致性的场景;BlockingQueue 中 ArrayBlockingQueue 有界稳定,LinkedBlockingQueue 无界易OOM;ThreadLocal 需及时 remove 避免内存泄漏。
因为 ConcurrentHashMap 不锁整个表,而是把桶数组分段加锁(JDK 7)或用 volatile + CAS + synchronized 控制单个 Node(JDK 8+),而 Hashtable 所有方法都用 synchronized 锁住整个实例。
实操建议:
ConcurrentHashMap;Hashtable 已基本淘汰,除非维护老代码ConcurrentHashMap 的 computeIfAbsent 是线程安全的,但注意其参数函数不能有副作用,否则可能被重复执行ConcurrentHashMap.keySet().iterator() 做遍历时修改操作——它不抛 ConcurrentModificationException,但行为不可靠,应改用 forEach 或 entrySet().parallelStream()
CopyOnWriteArrayList 在写操作(add/remove/set)时复制整个底层数组,读操作完全无锁。这意味着读性能极高、迭代绝对安全,但写操作代价大、内存占用翻倍、且读到的可能是“旧快照”。
实操建议:
add:每次 add 都触发一次数组复制,O(n) 时间 + O(n) 内存分配size() 和 get(int) 是弱一致性——调用瞬间返回当前快照长度/元素,但无法反映其他线程刚提交的写入两者都是线程安全的阻塞队列,但底层结构和性能特征差异明显。
实操建议:
ArrayBlockingQueue 是有界、基于数组、单锁(ReentrantLock)控制入队出队,吞吐量稳定,内存占用可控;适合对资源上限敏感的场景(如限流缓冲区)LinkedBlockingQueue 默认无界(容易 OOM),基于链表,入队出队分别用两个独立锁(takeLock / putLock),读写可并行,吞吐更高;若指定容量,才真正具备背压能力LinkedBlockingQueue 处理外部不可控数据流——生产者过快会撑爆堆内存ThreadLocal 的底层是每个线程持有一个 ThreadLocalMap,其中 key 是弱引用的 ThreadLocal 实例,value 是强引用。如果线程长期运行(如线程池中的线程),而 ThreadLocal 又没被显式 remove(),就会导致 value 无法回收,形成内存泄漏。
实操建议:
threadLocal.remove(),尤其在 finally 块里StringBuilder、缓存 Map)长期绑定在 ThreadLocal 中,即使及时 remove,也可能在 GC 前已造成压力InheritableThreadLocal 的子类重写 childValue,但要注意父子线程间的数据拷贝开销
并发容器不是银弹——ConcurrentHashMap 不能替代手动同步复杂复合操作,CopyOnWriteArrayList 不适合高频写,BlockingQueue 的边界策略直接影响系统稳定性,而 ThreadLocal 的生命周期必须和线程生命周期对齐。这些细节一旦忽略,问题往往在线上压测或流量高峰时才暴露。