我已经准备好了一些关于使用WeakReference
,SoftReference
等的问题。但是,我仍然不清楚在下列情况下我应该使用什么:
考虑一个名为Manager
的大师班。整个应用程序只有一个实例,它包含许多其他类(称为WorkerA
,WorkerB
......等等)作为成员:
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
=生命周期的生命周期,它在开头创建一次并在出口处处理。除了管理者的构造函数之外,Workers永远不会在其他地方实例化。
如何保持这些交叉引用内存的要求? (我的应用程序是Android服务,应该运行很长时间)。是否有更好的解决方案具有相同的功能?
答案 0 :(得分:2)
指向持有对另一个对象的引用的字段的成本并不重要。
持有引用的字段的成本在每个字段64位cpu上为64位,在32位cpu上为较少,或者虚拟机正在使用压缩指针时。 GC运行时,cpu成本也会非常低。这是因为GC循环的成本与存在的活动对象的数量以及它们之间的链接有关。但是,使用soft / weak / phantom引用时,内存使用和cpu的成本都会增加。这是因为它们需要额外的对象分配,这些对象分配大于一个字段,并且它们需要在GC循环期间进行特殊处理,这需要花费cpu时间。
使用特殊弱/软件等参考的时间是当您打算在某个时刻放下对象并且正常的GC生命周期不够时。由于您保留了应用程序生命周期中的对象,因此您的方法已经完善。
答案 1 :(得分:1)
除了使Manager
类成为单例类之外,我不会对Worker
对象使用软引用或弱引用。你想要的最后一件事就是当你最不期望它时(即当你调用那个对象做一些工作时)垃圾收集器回收Worker
对象的内存。使用普通的Java引用(即强引用),这不会发生。这里提到的不同类型的引用只决定了这些引用类型如何与垃圾收集器交互:垃圾收集器急切地回收弱引用,而不那么急切地回收软引用。
由于您现在还指定Manager
负责Worker
个对象的生命周期,因此使用弱/软引用更是一个静音点。当您希望GC确定是否可以回收特定对象内存而不是手动尝试自己确定时,您只能使用这些类型的引用。