在 Java 中使用哪种类型的引用?

Which type of reference to use in Java?

我这里准备了一些关于WeakReferenceSoftReference等用法的问题。但是,我仍然不清楚在以下情况下我应该使用什么:

考虑一位名为 Manager 的大师 class。整个应用程序只有一个实例,它包含许多其他 classes(称它们为 WorkerAWorkerB... 等等)作为成员:

public class Manager {
     private final WorkerA wA;
     private final WorkerB wB;
     ...
     public Manager()
     {
         wA = new WorkerA(this);
         ...
     }
}

因此 Manager 可以随时到达它的 Workers 并调用它们的方法。 然而,有时甚至工人也必须与他们的经理沟通,所以他们都包含对经理唯一实例的相同引用:

class WorkerA {
   private final Manager mgr;

   public WorkerA(Manager mgr)
   { this.mgr = mgr; }
}

Manager的生命周期=应用的生命周期,一开始创建一次,退出时销毁。除了在管理器的构造函数中,工人永远不会在其他任何地方实例化。

保存这些交叉引用的内存要求如何? (我的应用程序是一个 Android 服务,应该 运行 很长时间)。有相同功能的更好解决方案吗?

除了使 Manager class 成为单例 class 之外,我不会对 Worker 对象使用软引用或弱引用。你最不想要的是 Worker 对象的内存在你最不期望的时候被垃圾收集器回收(即当你调用该对象做一些工作时!)。对于普通的 Java 引用(即强引用),这不会发生。这里提到的不同类型的引用只决定了这些引用类型如何与垃圾收集器交互:弱引用被垃圾收集器急切回收,而软引用不那么急切回收。

既然您现在还指定了 Manager 负责 Worker 对象的生命周期,那么使用 weak/soft 引用就更像是一个沉默点。当您希望 GC 确定是否可以回收特定对象内存时,您只使用这些类型的引用,而不是手动尝试自己确定。

指向持有对另一个对象的引用的字段的成本并不重要。

持有引用的字段的成本将是 64 位,每个字段 64 位 cpu,32 位 cpu 或虚拟机使用压缩指针时更少。 GC 运行时也会有非常轻微的 cpu 成本。这是因为 GC 周期的成本与存在的活动对象数量以及它们之间的链接有关。但是,使用 soft/weak/phantom 引用时,内存使用和 cpu 的成本都会增加。这是因为它们需要比字段更大的额外对象分配,并且它们需要在 GC 循环期间进行特殊处理,这会花费 cpu 时间。

使用特殊weak/soft etc 引用的时间是当您打算在某个时候删除对象并且正常的GC 生命周期不够时。由于您在应用程序的整个生命周期内保留对象,因此您的方法已经很合理了。