面试题答案
一键面试选择合适的Map实现类
- HashMap:非线程安全,在高并发读写场景下会出现数据不一致等问题,不适合高并发场景。
- ConcurrentHashMap:线程安全,适用于高并发场景。在JDK 1.7及以前采用分段锁机制,允许多个线程同时访问不同段的数据,提高并发性能;JDK 1.8及以后采用CAS + 内置锁(synchronized)的方式,进一步提升并发性能。
性能特点和潜在问题
- HashMap
- 性能特点:在单线程环境下性能极高,因为没有线程安全的开销。
- 潜在问题:在高并发写操作时,可能会出现数据覆盖、链表死循环等问题。比如在扩容时,多个线程同时操作可能导致链表结构变化异常。
- ConcurrentHashMap
- 性能特点
- JDK 1.7及以前,分段锁机制使得不同线程可以同时操作不同段的数据,读操作一般不需要加锁,性能较好。
- JDK 1.8及以后,CAS操作减少了锁的竞争,并且读操作几乎无锁,并发性能进一步提升。
- 潜在问题
- JDK 1.7及以前,虽然分段锁提升了并发度,但锁粒度相对较大,某些情况下还是会影响性能。
- JDK 1.8及以后,虽然CAS操作提升了性能,但在高竞争环境下,CAS操作失败重试会消耗额外资源。
- 性能特点
性能优化
- 数据结构设计
- 合理预估容量:提前根据数据量预估Map的容量,减少扩容带来的性能开销。例如,在创建ConcurrentHashMap时,通过构造函数指定初始容量。
- 选择合适的负载因子:默认负载因子是0.75,平衡了空间和时间性能。如果对空间比较敏感,可适当降低负载因子;如果对时间性能要求高,可适当提高负载因子,但会增加哈希冲突的概率。
- 锁机制调整
- JDK 1.7及以前:合理调整分段数量,使得并发度和锁竞争达到平衡。如果分段数过多,会增加内存开销;分段数过少,锁竞争会加剧。
- JDK 1.8及以后:虽然CAS + synchronized的方式已经优化了锁机制,但在极端高并发场景下,可以考虑减少竞争。比如,将数据按照一定规则分区,不同线程操作不同分区的数据,减少对同一个桶(bucket)的竞争。