什么时候应该使用弱引用?

我最近遇到了一段带有WeakReferences的Java代码 – 我从未见过它们已部署,尽管我们在介绍时遇到过它们。 这是应该常规使用的东西,还是只有在遇到内存问题时? 如果是后者,它们是否可以轻松改装或代码是否需要严格的重构? 普通的Java(或C#)程序员通常会忽略它们吗?

编辑过度使用WR可以造成任何损害吗?

弱引用都是关于垃圾收集。 标准对象不会“消失”,直到对它的所有引用都被切断,这意味着在垃圾收集将其视为垃圾之前,必须删除各种对象必须删除的所有引用。

使用弱引用只是因为您的对象被其他对象引用并不一定意味着它不是垃圾。 它仍然可以被GC拾取并从内存中删除。

一个例子:如果我的应用程序中有一堆Foo对象,我可能想使用Set来保存我所有Foo的中心记录。 但是,当我的应用程序的其他部分通过删除对它的所有引用来删除Foo对象时,我不希望我的Set保留的剩余引用保持该对象以防止它被垃圾回收! 真的,我只是希望它从我的套装中消失。 这是你使用类似弱集(Java有一个WeakHashMap)的东西,它使用对其成员的弱引用而不是“强”引用。

如果您的对象在您想要它们时没有被垃圾收集,那么您在保存书中时会出错,某些内容仍然存在您忘记删除的引用。 使用弱引用可以减轻这种簿记的痛苦,因为您不必担心它们保持对象“活着”并且不进行垃圾回收,但您不必使用它们。

只要您想要引用对象而不保持对象自己存活,就可以使用它们。 这对于许多类似缓存的function来说都是如此,但在事件处理中也起着重要作用,其中订阅者不能通过订阅事件来保持活跃。

一个小例子:一个刷新一些数据的计时器事件。 任何数量的对象都可以在计时器上订阅以获得通知,但是他们在计时器上订阅的这个事实不应该使它们保持活动状态。 所以计时器应该对对象有弱引用。

过度热情地使用WR可以造成任何损害吗?

是的,它可以。

一个问题是弱引用会使您的代码更复杂并且可能容易出错。 任何使用弱引用的代码都需要处理每次使用它时引用被破坏的可能性。 如果过度使用弱引用,最终会编写大量额外代码。 (您可以通过隐藏负责检查的方法后面的每个弱引用来缓解这种情况,并根据需要重新创建丢弃的对象。但这可能不一定那么简单;例如,如果重新创建过程涉及网络访问,你需要应对重新创建失败的可能性。)

第二个问题是使用弱引用存在运行时开销。 显而易见的成本是创建弱引用并调用get on。 不太明显的成本是每次GC运行时都需要进行大量的额外工作。

最后一个问题是,如果您对将来很可能需要的某些内容使用弱引用,则可能会产生重复重新创建它的成本。 如果此成本很高(就CPU时间,IO带宽,网络流量而言等),您的应用程序可能会因此而表现不佳。 你可能最好给JVM提供更多的内存,而根本不使用弱引用。

当然,这并不意味着你应该完全避免使用弱引用。 只是你需要仔细思考。 您可能应首先在应用程序上运行内存分析器,以确定内存使用问题的来源。

在考虑使用WeakReference时要问的一个很好的问题是,如果弱引用在对象存在的强引用中无效,人们会感觉如何。 如果这会使WeakReference不那么有用,那么WeakReference可能不是最好用的。 如果这将是对垃圾收集产生的非确定性失效的改进,那么WeakReference可能是正确的选择。