| 場景 | 推薦類 | 特點 |
| 高併發讀寫 | ConcurrentHashMap | JDK 8+ CAS + synchronized (節點) + 分段鎖 → 細粒度,性能極佳 |
| 讀多寫少、需快照 | CopyOnWriteMap (Guava) / 自行包裝 | 寫時復制,讀無鎖,適合配置表 |
| 需保持插入順序 | ConcurrentSkipListMap (有序) / LinkedHashMap + Collections.synchronizedMap | 前者並發有序,後者粗粒度鎖 |
| 簡單計數/緩存 | LongAdder / AtomicLong + ConcurrentHashMap | 原子計數器避免 Map 開銷 |
ConcurrentHashMap 核心原理 (JDK 1.8+)
- 數組
Node[] table + 鏈表/紅黑樹 (鏈表長度 > 8 樹化)。
putVal:計算索引 → tab[i] == null → CAS 放入節點;否則 synchronized (首節點) 鎖住鏈表/樹頭節點操作。
size():LongAdder 思想,CounterCell[] 分段計數 + baseCount。
- 擴容:多線程協助擴容 (
transfer),每線程負責一段索引區間。
避坑指南
- HashMap 多線程導致死循環:JDK 7 擴容頭插法反轉鏈表形成環,JDK 8 改為尾插法但仍非線程安全 → 必須用
ConcurrentHashMap 或 Collections.synchronizedMap。
- 作為 Key 的對象必須不可變:覆寫
equals/hashCode,且字段 final (如 String、包裝類、自定義不可變類)。
- 初始容量預估:
new HashMap((int)(expectedSize/0.75)+1) 避免多次擴容。
- 遍歷中刪除:用
Iterator.remove() 或 map.entrySet().removeIf() (Java 8+)。
- 上一篇文章: JDK 環境變量配置精要:JAVA_HOME、Path 與 classpath 真相
- 下一篇文章: Collection vs Collections:一個字母之差,接口與工具類的本質區別
Copyright ©
程式碼之家 All Rights Reserved