小能豆

为什么Java的Cleaner使用链表而不是ConcurrentHashSet?

javascript

1

Java 的Cleaner底层使用双向链表来保存PhantomReferences,直到它们的所指对象变得幻像可达。当Cleaner’s守护线程弹出并PhantomReference从其中删除aReferenceQueue并将其从列表中删除时,整个列表必须被锁定(删除代码在@synchronized列表中)。

相比之下,aConcurrentHashMap仍然可以提供对 s 的 O(1) 访问PhantomReference,而且还可以通过让多个清理线程PhantomReference同时从映射中删除 s(作为键)来支持并发修改。

Java 采用双向链表方法有什么原因吗?是否因为 aCleaner仅使用单个守护线程进行清理,因此缺乏并发性并不重要?或者说这个选择有更深层次的原因吗?


阅读 180

收藏
2024-02-23

共1个答案

小能豆

Java 中的 Cleaner 类使用双向链表来保存 PhantomReference 的原因主要是因为它的实现是单线程的,守护线程会周期性地清理虚引用,并且 Java 的并发框架提供了其他适用于并发环境的数据结构,比如 ConcurrentHashMap

下面是一些可能的原因:

  1. 简单性和可靠性:双向链表是一种简单而且可靠的数据结构,容易理解和实现。对于 Cleaner 的实现来说,这种简单的数据结构足以满足其需求。
  2. 守护线程的单一性Cleaner 使用单个守护线程来清理虚引用,因此不需要考虑并发修改的情况。在这种情况下,使用简单的双向链表已经足够了,而不需要复杂的并发数据结构。
  3. 性能考虑:在单线程情况下,双向链表的性能可能比并发数据结构更好。对于单线程情况,使用简单的数据结构可以减少额外的同步开销,并且可能更高效。

总的来说,选择双向链表作为 Cleaner 内部数据结构的主要原因是为了简单性和性能考虑,并且因为它是单线程的实现,不需要复杂的并发支持。

2024-02-23