ConcurrentHashMap
和Hashtable
的区别主要体现在实现线程安全的⽅式上不同。
- 底层数据结构:JDK1.7 的
ConcurrentHashMap
底层采⽤分段的数组+链表实现,JDK1.8 时采⽤的数据结构跟HashMap
1.8 的结构⼀样,数组+链表/红⿊⼆叉树。Hashtable
和 JDK1.8 之前的HashMap
的底层数据结构类似都是采⽤ 数组+链表 的形式,数组是HashMap
的主体,链表则是主要为了解决哈希冲突⽽存在的; - 实现线程安全的⽅式(重要):① 在 JDK1.7 的时候,
ConcurrentHashMap
(分段锁)对整个桶数组进⾏了分割分段(Segment
),每⼀把锁只锁容器其中⼀部分数据,多线程访问容器⾥不同数据段的数据,就不会存在锁竞争,提⾼并发访问率。到了 JDK1.8 的时候已经摒弃了Segment
的概念,⽽是直接⽤Node
数组+链表+红⿊树的数据结构来实现,并发控制使⽤synchronized
和CAS
来操作。(JDK1.6 以后对synchronized
锁做了很多优化)整个看起来就像是优化过且线程安全的HashMap
,虽然在 JDK1.8 中还能看到Segment
的数据结构,但是已经简化了属性,只是为了兼容旧版本;②Hashtable
(同⼀把锁):使⽤synchronized
来保证线程安全,效率⾮常低下。当⼀个线程访问同步⽅法时,其他线程也访问同步⽅法,可能会进⼊阻塞或轮询状态,如使⽤put
添加元素,另⼀个线程不能使⽤put
添加元素,也不能使⽤get
,竞争会越来越激烈,效率很低。
两者的对⽐图:
HashTable:
JDK1.7 的 ConcurrentHashMap:
JDK1.8 的 ConcurrentHashMap:
JDK1.8 的 ConcurrentHashMap
不在是Segment 数组 + HashEntry 数组 + 链表,⽽是Node 数组 + 链表/红⿊树。不过,Node
只能⽤于链表的情况,红⿊树的情况需要使⽤TreeNode
。当冲突链表达到⼀定⻓度时,链表会转换成红⿊树。
留言