面试题答案
一键面试HashMap在高并发场景下的性能问题
- 线程安全问题:HashMap 是非线程安全的,在高并发环境下多个线程同时操作可能导致数据不一致,例如在扩容时可能形成环形链表,进而导致死循环。
- 性能瓶颈:当多个线程同时进行 put 操作时,由于哈希冲突,可能会导致链表过长,查询性能会从 O(1) 退化到 O(n)。
优化方式
- 使用线程安全的集合类:
- ConcurrentHashMap:它采用分段锁机制,允许多个线程同时访问不同段的数据,大大提高了并发性能。在 JDK 1.8 后,采用数组 + 链表 / 红黑树结构,并且锁粒度进一步细化到节点级别。
- Hashtable:虽然它是线程安全的,但它使用的是全局锁,在高并发场景下性能较差,不推荐使用。
- 减小哈希冲突:合理设置初始容量和负载因子,避免频繁扩容,同时选择一个好的哈希函数,尽量均匀地分布元素,减少链表过长的情况。
高性能键值对存储结构选择及优化策略
选择 ConcurrentHashMap
- JDK 1.7 优化策略:
- 分段锁设计:将数据分成多个段(Segment),每个段都有自己的锁,不同段的数据操作可以并发进行,提高并发度。
- 合理设置段数:根据预估的并发访问量,合理设置段数,以平衡锁竞争和内存开销。
- JDK 1.8 优化策略:
- 锁粒度细化:引入 CAS 操作和 synchronized 关键字对节点级别的操作进行控制,进一步降低锁的粒度,提高并发性能。
- 红黑树优化:当链表长度超过阈值(8)时,链表会转换为红黑树,提高查找性能,从 O(n) 提升到 O(log n)。
- 合理设置初始容量:根据预估的数据量,设置合适的初始容量,减少扩容带来的性能损耗。