幕后的Java Cleaner使用一个双向链表来保存PhantomReference,直到它们的对象变为幻影可达.当Cleaner‘S守护程序线程弹出并从其ReferenceQueue中删除PhantomReference并将其从列表中删除时,必须锁定整个列表(删除代码为列表上的@synchronized).

相比之下,ConcurrentHashMap仍然可以提供对PhantomReference的O(1)访问,但也可以通过允许多个清理线程同时从映射中删除PhantomReference(作为键)来支持并发修改.

Java采用双向链表方法有什么原因吗?是不是因为Cleaner只使用单个守护进程线程进行清理,所以缺乏并发性并不重要?或者,这种 Select 还有更深层次的原因吗?

推荐答案

使用双向链表的性能比使用ConcurrentHashMap要好得多,因为清理器使用的是双向链表的 node 对象.

删除 node 只是调整列表中的两个指针(一个来自上一个 node ,一个来自下一个 node ),并调整当前 node 中的两个指针(将其标记为已移除).它的源代码是12行代码(https://github.com/openjdk/jdk21u/blob/master/src/java.base/share/classes/jdk/internal/ref/PhantomCleanable.java#L101).

将这12行代码与ConcurrentHashMap删除单个条目所需的工作(https://github.com/openjdk/jdk21u/blob/master/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java#L1110)进行比较:这是超过70行的代码,而且代码要复杂得多.

这两种操作都是O(1),但这并不意味着ConcurrentHashMap只需要相同的时间--它只是意味着在两种数据 struct 中,当包含更多数据时,运行时不会增加.

Java相关问答推荐

编译期间错误(Java 0000)Android .Net MAUI

尽管类型擦除,instanceof与泛型在Java中如何工作?

上下文初始化期间遇到异常-使用Java配置配置HibernateTemplate Bean时

安装Java Jar应用程序的Install4j遇到ClassNotFoundException的运行时错误

Helidon 4和Http API

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

@Rollback @ Transmission在验收测试中不工作

在学习Spring时,通过构造函数参数0表达了不满意的依赖关系

有效的公式或值列表必须少于或等于255个字符

Java创建带有扩展通配符的抽象处理器

有谁能帮我修一下这个吗?使输出变得更加整洁

如何在Java springboot中从一个端点发送多个时间响应?

将双倍转换为百分比

Java中的发布/订阅-Long Live和Short Live Publisher,哪种方法是正确的?

接受类及其接口的Java类型(矛盾)

如何在Spring Boot中为不同的部署环境管理多个.properties文件?

Cucumber java-maven-示例表-未定义一步

谷歌应用引擎本地服务器赢得';t在eclipse上运行

java21预览未命名的符号用于try-with-resources

在java中使用SevenZip.openArchive方法后无法删除文件