【问题标题】:Smart Pointers and Ref Counting in JavaJava中的智能指针和引用计数
【发布时间】:2012-09-14 17:12:41
【问题描述】:

我正在尝试用 Java 编写 DagNode 类,其中两个节点在逻辑上相等,如果它们作为引用相等。

C++(我来自 C++)中的想法是使用智能指针和引用计数:

  • 创建节点后,如果该节点已存在,我将在某个表中查找。如果是这样,我将返回一个指向旧指针的指针。否则,创建一个新节点。

  • 重载的 C++ 方法(如复制构造函数和析构函数)会进行 ref-counting,当节点的 ref-count 降至 0 时,该节点会从上述表中逐出。 (C++ 也会释放内存。)

但是,似乎没有办法在 Java 中自动进行引用计数。我需要进行引用计数以知道何时从表中驱逐一个节点(以便它可以被垃圾收集),我真的想避免在每个开始和结束时调用 node->incRef()node->decRef()功能。

我们如何在 Java 中实现这个 C++ 习语?

【问题讨论】:

    标签: java smart-pointers refcounting


    【解决方案1】:

    在Java中,参考调查和垃圾是自动的。

    但这并不意味着它完全隐藏了。

    如果您想知道何时可以对对象进行垃圾处理,您似乎需要ReferenceQueue,如果您想保留不阻止垃圾处理的指针,则可能需要WeakReference

    我建议您查看java.lang.ref package 的描述,以找到最适合您需求的解决方案。

    【讨论】:

    • Java 中的引用计数不是自动的 - Java GC 根本不依赖引用计数。
    • 请允许我重复一遍,以确保我理解。基本上我有一个 WeakReference 的表,ReferenceQueue 的重点是当 WeakReference 无论如何都被 GC 时从表中逐出。表中有 WeakReference 意味着它仍然可以被 GC 处理,但如果堆栈或其他对象中有常规引用,则它不能被 GC 处理。并且 ReferenceQueue 确保从表中逐出发生在垃圾收集之前,所以一切都很好。
    • 这是一个非常优雅的解决方案! Java 给我留下深刻印象的情况并不常见。
    【解决方案2】:

    当一个节点被创建时,你在某个表中查找该节点是否已经存在,如果存在则返回一个指向旧节点的指针,否则创建新节点。

    在 Java 中创建这种查找机制并不难。只需使用工厂方法,它会检查“表”并返回相同的实例(如果它已经存在)。

    我需要引用计数,所以我知道何时从表中逐出一个节点(以便它可以被垃圾收集)

    Java 有 WeakReference 类。它不允许您进行引用计数,但允许在没有人引用该对象时对其进行 GC。

    结合这两个,你可以

    • 构造一个填充有WeakReferences 的“表”
    • 使用使用WeakReferences 的可用Java Collection 实现之一(例如WeakHashmap

    【讨论】:

      【解决方案3】:

      用于确定性资源管理的引用计数可以在 Java 中实现。如果您正在使用不由 GC 直接管理的任何类型的系统资源,它会很有用。 GC 管理堆内存。但是,如果您使用任何其他类型的资源,例如文件句柄、网络套接字或 本机内存,则不能依赖 GC(或其机制,例如 finalization 或 ReferenceQueue),因为您可能发现你已经分配了所有的资源,但是 GC 仍然没有开始,因为还有大量的 Java 堆内存。 (使用 finalization/ReferenceQueue 时要非常小心--they should never be relied upon

      看看almson-refcount。这是我在找不到任何独立替代方案后为引用计数而创建的库。它非常简单,并受到另一个成熟框架的启发。


      关于 OP 的问题,尚不清楚他们实际需要什么。他们绝对没有使用系统资源。听起来他们想要一个与 DAG 平行的 HashMap 以优化get。显而易见的方法是使 DAG 双向链接,并在从 DAG 中删除节点时从地图中删除节点。他们不需要 WeakReferences 或通用的引用计数,尽管两者都可以使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 2015-10-30
        • 2017-03-20
        • 1970-01-01
        • 1970-01-01
        • 2010-10-18
        相关资源
        最近更新 更多