简体   繁体   English

为什么我们需要java中的弱引用

[英]Why do we need weak reference in java

I understand that weak references are at the mercy of the garbage collector, and we cannot guarantee that the weak reference will exist. 我知道弱引用受到垃圾收集器的支配,我们不能保证弱引用会存在。 I could not see a need to have weak reference, but sure there should be a reason. 我看不出需要弱参考,但确定应该有理由。

  • Why do we need weak reference in java? 为什么我们需要java中的弱引用?
  • What are the practical (some) uses of weak reference in java? java中弱引用的实际(某些)用法是什么? If you can share how you used in your project it will be great! 如果您可以分享您在项目中的使用方式,那就太棒了!

It's actually quite often a bad idea to use weak hashmaps. 使用弱哈希映射实际上通常是一个坏主意。 For one it's easy to get wrong, but even worse it's usually used to implement some kind of cache. 一方面容易出错,但更糟糕的是它通常用于实现某种缓存。

What this does mean is the following: Your program runs fine with good performance for some time, under stress we allocate more and more memory (more requests = more memory pressure = probably more cache entries) which then leads to a GC. 这意味着以下内容:您的程序在一段时间内运行良好且性能良好,在压力下我们分配越来越多的内存(更多请求=更多内存压力=可能更多缓存条目),然后导致GC。

Now suddenly while your system is under high stress you not only get the GC, but also lose your whole cache, just when you'd need it the most. 现在,当您的系统处于高压力状态时,您不仅会获得GC,而且还会丢失整个缓存,就在您最需要它时。 Not fun this problem, so you at least have to use a reasonably sized hard referenced LRU cache to mitigate that problem - you can still use the weakrefs then but only as an additional help. 这个问题并不好玩,所以你至少必须使用一个合理大小的硬引用LRU缓存来缓解这个问题 - 你仍然可以使用weakrefs,但仅作为额外的帮助。

I've seen more than one project hit by that "bug".. 我看过不止一个项目被“虫子”击中..

The most "unambiguously sensible" use of weak references I've seen is Guava's Striped , which does lock striping. 我见过的最简单明智的弱引用使用是Guava的Striped ,它可以锁定条带。 Basically, if no threads currently hold a reference to a lock variable, then there's no reason to keep that lock around, is there? 基本上,如果没有线程当前持有对锁变量的引用,那么没有理由保持锁定,是吗? That lock might have been used in the past, but it's not necessary now. 这个锁可能在过去曾被使用过,但现在没必要了。

If I had to give a rule for when you use which, I'd say that soft references are preferable when you might use something in the future, but could recompute it if you really needed it; 如果我必须在你使用它的时候给出一个规则,我会说当你将来可以使用某些东西时,软引用是可取的,但是如果你真的需要它可以重新计算它; weak references are especially preferable when you can be sure the value will never be needed after a reference goes out of memory. 当您可以确定在引用内存不足后永远不需要该值时,弱引用尤其可取。 (For example, if you use the default reference equality for a particular equals(Object) implementation for a map key type, and the object stops being referenced anywhere else, then you can be sure that entry will never be referenced again. (例如,如果对映射键类型使用特定equals(Object)实现的默认引用相等性,并且该对象在其他任何位置停止引用,则可以确保该条目永远不会再次引用。

The main reason for me to use weak references is indirectly, through a WeakHashMap. 我使用弱引用的主要原因是间接地通过WeakHashMap。

You might want to store a collection of objects in a Map (as a cache or for any other reason), but don't want them to be in memory for as long as the Map exists, especially if the objects are relatively large. 您可能希望在Map中存储对象集合(作为缓存或出于任何其他原因),但是只要Map存在,就不希望它们存在于内存中,尤其是在对象相对较大的情况下。

By using a WeakHashMap, you can make sure that the reference from the Map isn't the only thing keeping the object in memory, since it'll be garbage collected if no other references exist. 通过使用WeakHashMap,您可以确保来自Map的引用不是将对象保留在内存中的唯一方法,因为如果不存在其他引用,它将被垃圾收集。

假设您需要保留一些信息,只要引用了一个对象,但您不知道它什么时候会消失,您可以使用弱引用来跟踪信息。

Yes and it has good impact. 是的,它有很好的影响力。

Example of " widget serial number " problem above, the easiest thing to do is use the built-in WeakHashMap class. 上面的“ 小部件序列号 ”问题示例,最简单的方法是使用内置的WeakHashMap类。 WeakHashMap works exactly like HashMap , except that the keys (not the values!) are referred to using weak references. WeakHashMap工作方式与HashMap完全相同,只是使用弱引用引用键(而不是值!)。 If a WeakHashMap key becomes garbage, its entry is removed automatically. 如果WeakHashMap键变为垃圾,则会自动删除其条目。 This avoids the pitfalls I described and requires no changes other than the switch from HashMap to a WeakHashMap . 这避免了我描述的陷阱,除了从HashMap切换到WeakHashMap之外不需要任何更改。 If you're following the standard convention of referring to your maps via the Map interface, no other code needs to even be aware of the change. 如果您遵循通过Map接口引用地图的标准惯例,则其他代码甚至不需要知道更改。

Reference 参考

Weak Refernce Objects are needed to JVM platform to ensure means against the memory leaks. JVM平台需要弱引用对象以确保防止内存泄漏的手段。

As Java Developers should know, Java can leak, more than expected. 正如Java开发人员应该知道的那样,Java可能会泄漏,超出预期。 This statement is particurarly true in those cases in which an Object is no longer used but some collection still refence strongly that instance: a very simple but recurrent example of memory leak, in fact that memory area will not be deallocated until the strong reference exists. 在不再使用Object的情况下,这种说法尤其正确,但某些集合仍强烈反对该实例:一个非常简单但经常出现的内存泄漏示例,事实上在存在强引用之前,内存区域不会被释放。

In the above case, a Weak Reference Object in the collection assures that: without a strong references chain, but with only weak chains, the instance can be elcted as garbace collectable. 在上面的例子中,集合中的弱引用对象确保:没有强引用链,但只有弱链,实例可以作为garbace可收集。

In my opinion, all features provided by the Java Platform are useful to some extent: very skilled programmer can drive Java to be fast and reliable as C++ writing very high quality code. 在我看来,Java平台提供的所有功能在某种程度上都是有用的:非常熟练的程序员可以驱动Java快速可靠,因为C ++编写了非常高质量的代码。

It is required to make Java garbage collection deterministic . 需要使Java垃圾收集具有确定性 (From the slightly satirical point of view with some truth to it). (从略带讽刺的观点来看,有一些道理)。

Decoupling from pub-sub or event bus 与pub-sub或事件总线分离

A WeakReference is good when you want to let an object head for garbage-collection without having to gracefully remove itself from other objects holding an reference. 当你想让一个对象进行垃圾收集而不必优雅地将自己从持有引用的其他对象中移除时, WeakReference是很好的。

In scenarios such as publish-subscribe or an event bus, a collection of references to subscribing objects is held. 在诸如发布 - 订阅或事件总线的场景中,保持对订阅对象的引用的集合。 Those references should be weak, so that the subscriber can conveniently go out of scope without bothering to unsubscribe. 这些引用应该很弱,以便订户可以方便地超出范围而无需取消订阅。 The subscriber can just “disappear” after all other places in the app have released their strong reference. 在应用程序中的所有其他位置发布其强引用后,订阅者可以“消失”。 At that point, there is no need for the subscription list or event bus to keep hanging on to the subscriber. 此时,订阅列表或事件总线不需要继续挂在订户上。 The use of WeakReference allows the object to continue on its way into oblivion. WeakReference的使用允许对象继续被遗忘。

The subscribing object may have been subscribed without its knowledge, submitted to the pub-sub or event bus by some other 3rd-party object. 订阅对象可能在不知情的情况下订阅,由其他第三方对象提交给pub-sub或事件总线。 Coordinating a call to unsubscribe later in the life-cycle of the subscriber can be quite cumbersome. 在订户的生命周期中协调要取消订阅的呼叫可能非常麻烦。 So letting the subscriber fade away without formally unsubscribing may greatly simplify your code, and can avoid difficult bugs if that unsubscribing coordination were to fail. 因此,在没有正式取消订阅的情况下让订阅者逐渐消失可能会大大简化您的代码,并且如果取消订阅协调失败,可以避免难以解决的错误。

Here is an example of a thread-safe set of weak references, as seen in this Answer and this Answer . 下面是一个线程安全的弱引用集的示例,如本答案本答案中所示

    this.subscribersSet =
            Collections.synchronizedSet(
                    Collections.newSetFromMap(
                            new WeakHashMap <>()
                    )
            );

Note that the entry in the set is not actually removed until after garbage-collection actually executes, as discussed in linked Answer above. 请注意,在实际执行垃圾收集之前实际上并未删除集合中的条目,如上面链接的答案中所述。 While existing as a candidate for garbage-collection (no remaining strong references held anywhere), the item remains in the set. 虽然作为垃圾收集的候选者存在(没有任何剩余的强引用),该项目仍然在集合中。

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

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