简体   繁体   English

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

[英]When should weak references be used?

I recently came across a piece of Java code with WeakReferences - I had never seen them deployed although I'd come across them when they were introduced. 我最近遇到了一段带有WeakReferences的Java代码 - 我从未见过它们已部署,尽管我们在介绍时遇到过它们。 Is this something that should be routinely used or only when one runs into memory problems? 这是应该常规使用的东西还是只有在遇到内存问题时? If the latter, can they be easily retrofitted or does the code need serious refactoring? 如果是后者,它们是否可以轻松改装或代码是否需要严格的重构? Can the average Java (or C#) programmer generally ignore them? 普通的Java(或C#)程序员通常会忽略它们吗?

EDIT Can any damage be done by over-enthusiastic use of WRs? 编辑过度使用WR可以造成任何损害吗?

Weak references are all about garbage collection. 弱引用都是关于垃圾收集。 A standard object will not "disappear" until all references to it are severed, this means all the references your various objects have to it have to be removed before garbage collection will consider it garbage. 标准对象在所有对它的引用被切断之前不会“消失”,这意味着在垃圾收集将其视为垃圾之前,必须删除各种对象必须删除的所有引用。

With a weak reference just because your object is referenced by other objects doesn't necessarily mean it's not garbage. 仅仅因为您的对象被其他对象引用而使用弱引用并不一定意味着它不是垃圾。 It can still get picked up by GC and get removed from memory. 它仍然可以被GC拾取并从内存中删除。

An example: If I have a bunch of Foo objects in my application I might want to use a Set to keep a central record of all the Foo's I have around. 一个例子:如果我的应用程序中有一堆Foo对象,我可能想使用Set来保存我所有Foo的中心记录。 But, when other parts of my application remove a Foo object by deleting all references to it, I don't want the remaining reference my Set holds to that object to keep it from being garbage collected! 但是,当我的应用程序的其他部分通过删除对它的所有引用来删除Foo对象时,我不希望我的Set的剩余引用保留到该对象以防止它被垃圾收集! Really I just want it to disappear from my set. 真的,我只是希望它从我的集合中消失。 This is where you'd use something like a Weak Set (Java has a WeakHashMap) instead, which uses weak references to its members instead of "strong" references. 这就是你使用类似弱集(Java有一个WeakHashMap)的东西,它使用对其成员的弱引用而不是“强”引用。

If your objects aren't being garbage collected when you want them to then you've made an error in your book keeping, something's still holding a reference that you forgot to remove. 如果您的对象在您想要它们时没有被垃圾收集,那么您在簿记中出错了,还有一些内容仍然存在您忘记删除的引用。 Using weak references can ease the pain of such book keeping, since you don't have to worry about them keeping an object "alive" and un-garbage-collected, but you don't have to use them. 使用弱引用可以缓解这种记帐的痛苦,因为你不必担心他们保持一个对象“活着”,并取消垃圾收集,但你没有使用它们。

You use them whenever you want to have a reference to an object without keeping the object alive yourself. 只要您想要对对象进行引用而不自己保持对象存活,就可以使用它们。 This is true for many caching-like features, but also play an important role in event handling, where a subscriber shall not be kept alive by being subscribed to an event. 这对于许多类似缓存的功能来说都是如此,但在事件处理中也起着重要作用,订阅者不应通过订阅事件来保持活跃。

A small example: A timer event which refreshes some data. 一个小例子:一个刷新一些数据的计时器事件。 Any number of objects can subscribe on the timer in order to get notified, but the bare fact that they subscribed on the timer should not keep them alive. 任何数量的对象都可以在计时器上订阅以获得通知,但是他们在计时器上订阅的这个事实不应该使它们保持活动状态。 So the timer should have weak references to the objects. 所以计时器应该对对象有弱引用。

Can any damage be done by over-enthusiastic use of WRs? 过度热情地使用WR可以造成任何损害吗?

Yes it can. 是的,它可以。

One concern is that weak references make your code more complicated and potentially error prone. 一个问题是弱引用会使您的代码更复杂并且可能容易出错。 Any code that uses a weak reference needs to deal with the possibility that the reference has been broken each time it uses it. 任何使用弱引用的代码都需要处理每次使用它时引用被破坏的可能性。 If you over-use weak references you end up writing lots of extra code. 如果过度使用弱引用,最终会编写大量额外代码。 (You can mitigate this by hiding each weak reference behind a method that takes care of the checking, and re-creates the discarded object on demand. But this may not necessarily be as simple as that; eg if the re-creation process involves network access, you need to cope with the possibility of re-creation failure.) (您可以通过隐藏负责检查的方法后面的每个弱引用来缓解这种情况,并根据需要重新创建丢弃的对象。但这可能不一定那么简单;例如,如果重新创建过程涉及网络访问,你需要应对重新创建失败的可能性。)

A second concern is that there are runtime overheads with using weak references. 第二个问题是使用弱引用存在运行时开销。 The obvious costs are those of creating weak references and calling get on them. 显而易见的成本是创建弱引用和调用get A less obvious cost is that significant extra work needs to be done each time the GC runs. 不太明显的成本是每次GC运行时都需要进行大量的额外工作。

A final concern is that if you use a weak references for something that your application is highly likely to need in the future, you may incur the cost of repeatedly recreating it. 最后一个问题是,如果您对应用程序很可能在将来需要的某些内容使用弱引用,则可能会产生重复重新创建它的成本。 If this cost is high (in terms of CPU time, IO bandwidth, network traffic, whatever) your application may perform badly as a result. 如果此成本很高(就CPU时间,IO带宽,网络流量而言),您的应用程序可能会因此而表现不佳。 You may be better off giving the JVM more memory and not using weak references at all. 你可能最好给JVM提供更多内存,而根本不使用弱引用。

Off course, this does not mean you should avoid using weak references entirely. 当然,这并不意味着你应该完全避免使用弱引用。 Just that you need to think carefully. 只是你需要仔细思考。 And probably you should first run a memory profiler on your application to figure out where your memory usage problems stem from. 您可能应首先在应用程序上运行内存分析器,以确定内存使用问题源于何处。

A good question to ask when considering use of a WeakReference is how one would feel if the weak reference were invalidated the instant no strong references existed to the object. 在考虑使用WeakReference时要问的一个很好的问题是,如果弱引用在对象存在的强引用中无效,人们会感觉如何。 If that would make the WeakReference less useful, then a WeakReference is probably not the best thing to use. 如果这会使WeakReference不那么有用,那么WeakReference可能不是最好用的。 If that would be an improvement over the non-deterministic invalidation that comes from garbage-collection, then a WeakReference is probably the right choice. 如果这将是对垃圾收集产生的非确定性失效的改进,那么WeakReference可能是正确的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM