面试题答案
一键面试性能方面
- Hashtable:
- 同步方式:Hashtable 对几乎所有的操作(如 get、put 等)都使用
synchronized
关键字进行同步,这意味着在多线程环境下,每次只能有一个线程访问 Hashtable 的方法,其他线程必须等待锁的释放。这种粗粒度的锁机制在高并发场景下,会导致大量线程竞争锁,从而增加线程上下文切换的开销,降低系统的整体性能。 - 吞吐量:由于锁的竞争激烈,在高并发读写操作时,Hashtable 的吞吐量会急剧下降,无法充分利用多核 CPU 的优势。
- 同步方式:Hashtable 对几乎所有的操作(如 get、put 等)都使用
- ConcurrentHashMap:
- 同步方式:ConcurrentHashMap 在 JDK 1.7 中采用分段锁机制,将整个哈希表分成多个段(Segment),每个段都有自己独立的锁。不同段上的操作可以并行进行,只有在访问同一个段时才需要竞争锁,大大降低了锁的竞争程度。在 JDK 1.8 中,放弃了分段锁机制,采用 CAS(Compare - and - Swap)和 synchronized 关键字来实现线程安全。在低竞争情况下,使用 CAS 操作提高性能,在高竞争情况下,使用 synchronized 对链表或红黑树的头节点进行同步,进一步提高了并发性能。
- 吞吐量:通过减少锁的粒度和优化同步机制,ConcurrentHashMap 在高并发场景下能够提供更高的吞吐量,充分利用多核 CPU 的计算能力,使得读写操作可以更高效地进行。
功能特性方面
- Hashtable:
- 空值处理:Hashtable 不允许键或值为 null。如果尝试插入 null 键或 null 值,会抛出
NullPointerException
。这在某些需要处理空值的业务场景中,会带来不便,需要额外的逻辑来处理这种情况。 - 迭代器特性:Hashtable 的迭代器是 fail - fast 的。这意味着在迭代过程中,如果集合结构被修改(除了通过迭代器自身的 remove 方法),迭代器会抛出
ConcurrentModificationException
。这在多线程环境下,可能会导致一些意外的异常,使得程序的健壮性受到影响。
- 空值处理:Hashtable 不允许键或值为 null。如果尝试插入 null 键或 null 值,会抛出
- ConcurrentHashMap:
- 空值处理:ConcurrentHashMap 同样不允许键为 null,但允许值为 null。这在一定程度上提供了更灵活的使用方式,对于一些业务逻辑中允许值为空的场景,不需要额外的特殊处理。
- 迭代器特性:ConcurrentHashMap 的迭代器是弱一致性的。在迭代过程中,即使集合结构被修改,迭代器也不会抛出
ConcurrentModificationException
,而是会尽力返回在迭代开始时的集合状态,并且可能会反映出迭代过程中发生的部分修改。这种特性在多线程环境下,能提供更稳定的迭代操作,增强了程序的健壮性和可预测性。