在Java中使用哪种类型的引用?
我在这里准备了一些关于在Java中使用哪种类型的引用?,java,android,reference,Java,Android,Reference,我在这里准备了一些关于WeakReference,SoftReference等用法的问题。。但是,我仍然不清楚在以下情况下应该使用什么: 考虑一个名为Manager的主类。整个应用程序只有一个实例,它包含许多其他类(称它们为WorkerA,WorkerB…等等)作为成员: public class Manager { private final WorkerA wA; private final WorkerB wB; ... public Manager
WeakReference
,SoftReference
等用法的问题。。但是,我仍然不清楚在以下情况下应该使用什么:
考虑一个名为Manager
的主类。整个应用程序只有一个实例,它包含许多其他类(称它们为WorkerA
,WorkerB
…等等)作为成员:
public class Manager {
private final WorkerA wA;
private final WorkerB wB;
...
public Manager()
{
wA = new WorkerA(this);
...
}
}
因此,经理
可以随时联系其工作人员
并调用他们的方法。
但是,有时甚至员工也必须与他们的经理进行沟通,因此所有员工都包含对经理唯一实例的相同引用:
class WorkerA {
private final Manager mgr;
public WorkerA(Manager mgr)
{ this.mgr = mgr; }
}
管理器的生存期
=应用程序的生存期,它在开始时创建一次,在退出时释放。除了在管理器的构造函数中,工人永远不会在其他任何地方实例化
保存这些交叉引用对内存的要求如何?(我的应用程序是一个Android服务,应该可以运行很长时间)。有没有更好的解决方案具有相同的功能?以及将
管理器
类设为单例类,我不会对工作者
对象使用软引用或弱引用。您最不希望工作者对象的内存在您最不希望的时候(即,当您调用该对象执行某些工作时!)被垃圾收集器回收。对于普通Java引用(即强引用),这不会发生。这里提到的不同类型的引用只决定了这些引用类型如何与垃圾收集器交互:垃圾收集器急切地回收弱引用,而软引用则不那么急切地回收
由于您现在还指定了管理器
负责工作者
对象的生存期,因此使用弱/软引用更像是一个静音点。只有当您希望GC确定某个特定对象的内存是否可以回收时,才可以使用这些类型的引用,而不是手动尝试自己确定。一个字段指向另一个对象的引用的成本并不显著
在64位cpu上,每个字段持有引用的字段的成本为64位,在32位cpu上或在虚拟机使用压缩指针时,成本更低。当GC运行时,cpu成本也会非常低。这是因为GC循环的成本与存在多少活动对象以及它们之间的链接有关。但是,当使用软/弱/幻影引用时,内存使用和cpu的成本都会增加。这是因为它们需要比字段更大的额外对象分配,并且在GC循环期间需要特殊处理,这会耗费cpu时间
使用特殊的弱/软etc引用的时间是当您打算在某个点删除对象,并且正常的GC生命周期不够时。既然您在应用程序的生命周期中保留了对象,那么您的方法已经很好了。首先,您的Manager类应该是单例类。其次,一旦创建了一个Worker
,它在应用程序退出之前是否存在?您需要为管理器和所有实例化的Worker提供内存,因为它们都将在应用程序生命周期中存在。我真的不明白你的意思吗?正如@I.K.所提到的,保存管理器实例的单个静态引用。好的,singleton本质上意味着拥有一个私有构造函数和一个用于实例化的公共静态方法,以及其他什么?所以所有的工人都称之为静态方法?他们的成本并不显著。在64位cpu上,每个字段保存引用的成本为64位。当GC运行时,cpu成本也会非常低。但是,当使用软/弱/幻影引用时,内存使用和cpu的成本都会增加。当您打算在某个时候丢弃对象,并且正常的GC生命周期还不够时,就需要使用它们。既然你在应用程序的生命周期中保留了这些对象,那么你的方法已经很好了。谢谢!最后一件事——你说,如果有一些worker(但很少)在应用程序退出之前被管理器销毁,我仍然不应该麻烦使用简单的对象引用以外的任何东西?如果worker关闭,那么我将从管理器中删除对worker的引用。我假设工人知道它正在关闭?在这种情况下,它可以通知经理自己。这将足以让GC发现可以清理对象。如果你听不到工人的停工声,那就是使用WeakReference的时候了。