我阅读了很多文章,但我不明白 - 在实践中我需要在哪里使用 Weak 和 Phantom 引用?据我了解,软引用 - 是缓存的不错选择。但是虚弱又虚幻,不知道什么时候用。请提供我们需要使用它们的实际任务的示例。
5 回答
您可以将弱引用用于缓存,就像您所说的软引用一样。
PhantomReferences 有什么好处?我只知道它们有两种严重的情况:首先,它们允许您准确确定对象何时从内存中删除。它们实际上是确定这一点的唯一方法。这通常不是那么有用,但在某些非常特定的情况下可能会派上用场,例如处理大图像:如果您确定图像应该被垃圾收集,您可以等到它实际上是在尝试加载下一个图像之前,因此减少了可怕的 OutOfMemoryError 的可能性。
其次,PhantomReferences 避免了终结的一个基本问题:finalize() 方法可以通过创建对它们的新强引用来“复活”对象。那你说呢?好吧,问题是覆盖 finalize() 的对象现在必须在至少两个单独的垃圾收集周期中被确定为垃圾才能被收集。当第一个循环确定它是垃圾时,它就有资格进行终结。由于对象在最终确定期间“复活”的可能性(很小,但不幸的是真实的),垃圾收集器必须再次运行,然后才能实际删除对象。并且因为终结可能没有及时发生,所以在对象等待终结时可能发生了任意数量的垃圾回收周期。
有关更多详细信息,请参阅此页面: http ://weblogs.java.net/blog/2006/05/04/understanding-weak-references
基本上,当您想将一些附加数据与源代码不受您控制的对象关联时,您将使用 Weak ref。通过使用弱引用,您可以将元对象的生命周期与主要对象的生命周期结合起来。
phantom refs 的主要用例是实现您自己的终结器线程,而不会出现与默认机制相关的危险,默认机制会强制引用对终结代码可访问的假定不可访问对象。
软引用主要用于缓存,但是,正如在此处的另一篇文章中所说,它们在实践中会产生非常灾难性的影响,从而破坏了缓存的意义。一个主要的 GC(将清除您的 Soft refs)通常不会发生,直到您的应用程序性能的压力增加。这是您最需要缓存的时候,也是您最有可能丢失缓存的时候——一次全部丢失。
这篇文章对这个问题有很好的回答。
我认为这篇文章很好地回答了你的问题。
基本上,软参考比弱参考稍强。弱引用将在下一个 GC 周期被丢弃,而软引用将保留在内存中,直到出现内存压力并且 JVM 想要尽可能多地回收。
您应该考虑您拥有的引用仍然有效对您的程序有多重要。对于重新创建引用非常便宜的东西,我倾向于使用 WeakReference,但如果它是来自数据库的值,您可能会倾向于软引用,因为除非您真的需要,否则您宁愿不重新运行查询。
直到所有 WeakReference 对象都被垃圾回收后,SoftReference 对象才会被回收。
所以把不太重要的对象放在 WeakReference 对象中,用 SoftReference 对象来持有更重要的对象。
鉴于这些事实,您应该根据垃圾收集的需要使用好的参考对象。首先收集 WeakReference,然后是 SoftReference,最后是 PhantomReferences。
- 软引用用于实现内存敏感缓存
- 弱引用用于实现不阻止其键(或值)被回收的规范化映射
顺便说一句,在某些情况下,出于缓存目的,使用 WeakReference 而不是 SoftReference 可能是个好主意,因为缓存在内存中可能很重,因此需要清理。
对于 PhantomReference,用途不同。他们are for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.
本文详细介绍了 PhantomReference 的用途。