我知道弱引用对象会受垃圾回收器的影响,我们不能保证弱引用会一直存在。我没有看到需要使用弱引用的必要性,但肯定有原因。
- 在Java中为什么需要使用弱引用?
- Java中弱引用的实际用途有哪些(一些)?如果您能分享您在项目中如何使用它将会很棒!
我知道弱引用对象会受垃圾回收器的影响,我们不能保证弱引用会一直存在。我没有看到需要使用弱引用的必要性,但肯定有原因。
使用弱哈希表通常是一个不好的想法。首先很容易出错,更糟糕的是它通常被用于实现某种类型的缓存。
这意味着以下内容:您的程序在一段时间内以良好的性能运行正常,在压力下我们会分配越来越多的内存(更多请求=更多内存压力=可能更多的缓存条目),这会导致垃圾回收。
现在,在系统处于高负荷状态时,您不仅会遇到垃圾回收,还会失去整个缓存,而这正是您最需要它的时候。这个问题并不好解决,因此您至少需要使用合理大小的硬引用LRU缓存来减轻这个问题-然后您仍然可以使用弱引用作为额外的辅助。
我曾见过不止一个项目遭受了这个“bug”的困扰...
Striped
,它执行锁条纹化。基本上,如果当前没有线程持有对锁变量的引用,那么就没有理由保留该锁了,是吧?那个锁可能曾经被使用过,但现在不再需要了。equals(Object)
实现,并且该对象停止在其他任何地方被引用,那么你可以确定该条目永远不会再次被引用。WeakReference
的情况下,弱引用存在的目的不是为了封装其目标的状态,而是为了封装其身份(即存在于其周围的其他引用集合)。如果该其他引用集合为空,则WeakReference
将停止封装任何有价值的内容。 - supercat我使用弱引用的主要原因是通过WeakHashMap间接实现。
你可能想在Map中存储一组对象(作为缓存或任何其他原因),但不希望它们在Map存在期间一直保留在内存中,特别是如果这些对象相对较大。
通过使用WeakHashMap,您可以确保引用不是唯一使对象保留在内存中的东西,因为如果不存在其他引用,则该对象将被垃圾回收。
如果您需要在对象被引用时保留某些信息,但不知道何时该对象会消失,您可以使用弱引用来跟踪这些信息。
是的,它有很好的影响。
以上"widget serial number"问题为例,最简单的方法是使用内置的
WeakHashMap
类。WeakHashMap
的工作方式与HashMap
完全相同,只是键(而不是值!)使用弱引用进行引用。如果一个WeakHashMap
键变成垃圾,它的条目将自动被删除。这避免了我所描述的陷阱,并且除了从HashMap
切换到WeakHashMap
之外,不需要进行任何更改。如果您按照通过Map
接口引用映射的标准约定,那么没有其他代码需要知道这种变化。
WeakReference
在你希望一个对象可以被垃圾回收而不必从持有对其引用的其他对象中优雅地移除自己时非常有用。
在 发布-订阅 或事件总线等场景中,会保存一组订阅对象的引用。这些引用应该是弱引用,以便订阅者方便地离开作用域而无需取消订阅。在所有应用程序中释放其强引用后,订阅者可以“消失”。此时,订阅列表或事件总线不需要继续保留对订阅者的引用。使用 WeakReference
允许对象继续进入遗忘之路。
订阅对象可能是由某个第三方对象提交到发布-订阅或事件总线中的,而不知道自己已经被订阅。在订阅者的生命周期后期协调调用取消订阅可能会非常麻烦。因此,让订阅者消失而不正式取消订阅可能会大大简化代码,并且如果取消订阅协调失败,则可以避免出现困难的错误。
这是一个线程安全的弱引用集合示例,可以在此答案和此答案中看到。 this.subscribersSet =
Collections.synchronizedSet(
Collections.newSetFromMap(
new WeakHashMap <>()
)
);
需要使Java垃圾收集器变得可预测(从略带讽刺的角度来看,具有一定的真实性)。