Java集合面试题, Java 中 ConcurrentHashMap 1.7 和 1.8 之间有哪些区别?
Java集合面试题, Java 中 ConcurrentHashMap 1.7 和 1.8 之间有哪些区别?
QA
Step 1
Q:: Java 中 ConcurrentHashMap 1.7 和 1.8
之间有哪些区别?
A:: Java 1.7 版本的 ConcurrentHashMap 采用分段锁 (Segmented Locks) 机制,将整个 Map 分成多个 Segment,每个 Segment 是一个小的 HashMap,并且带有自己的锁。Java 1.8 版本的 ConcurrentHashMap 采用了 CAS (Compare-And-Swap) 以及红黑树 (Red-Black Tree) 来替代分段锁。1.8
中的实现更加细粒度化,并且在高并发场景下性能更好。具体变化包括使用 Node 数组代替 Segment 数组,使用 CAS 操作来实现更高效的并发控制,以及当桶中的元素数量超过一定阈值时,将链表转换为红黑树以加快查找速度。
Step 2
Q:: 为什么 ConcurrentHashMap 在高并发情况下比 Hashtable 更好?
A:: Hashtable 对每个方法都使用 synchronized 进行同步,这样在高并发环境下会导致大量的线程争用锁,性能下降。ConcurrentHashMap 通过更细粒度的锁和无锁操作 (如 CAS) 来减少竞争,提升并发性能。特别是 Java 1.8
版本,通过引入红黑树结构优化了高并发环境下的性能。
Step 3
Q:: ConcurrentHashMap 的内部结构是怎样的?
A:: ConcurrentHashMap 在 Java 1.8 中由一个 Node 数组、一个锁表 (用于支持并发操作的细粒度锁)
以及链表或红黑树组成。当插入一个键值对时,首先通过 hash 算法找到对应的桶,如果桶为空则直接插入;如果桶不为空,则通过 CAS 插入。如果桶中已经有多个元素,则可能会形成链表或者红黑树结构,以提高查找和插入的效率。
Step 4
Q:: ConcurrentHashMap 的扩容机制是怎样的?
A:: 当 ConcurrentHashMap 中的元素数量达到一定阈值时,会触发扩容机制。扩容时,会创建一个新的、更大的数组,并将旧数组中的元素重新分布到新数组中。Java 1.8
中通过引入转移操作来实现这一过程,且在并发情况下,多个线程可以协同工作完成扩容,减少扩容的时间。
Step 5
Q:: 在什么情况下使用 ConcurrentHashMap 而不是 HashMap?
A:: ConcurrentHashMap 主要用于多线程环境下需要高效并发访问的场景。典型的使用场景包括缓存、计数器、汇总统计等。在这些场景中,多个线程可能同时读写数据,ConcurrentHashMap 提供了更高效的并发支持和性能。