弱引用允许 GC 在下一个 GC 循环中收集引用,而软引用将保留引用直到内存已满,并且在抛出内存错误之前,它将删除软引用。我们将在哪里使用这些参考资料?哪个参考最适合实现缓存?例如:如果我使用软引用进行缓存,那么当内存已满时它将被清除。但是让我们假设,我已经获取了一些数据库详细信息并将其放入内存并将该详细信息缓存在软引用中,现在如果我从内存中删除了一些键值,它仍然会存在缓存中。我们需要在此使用弱引用吗案例?应该如何做出决定。
4 回答
弱引用允许 GC 在下一个 GC 循环中收集引用,而软引用将保留引用直到内存已满,并且在抛出内存错误之前,它将删除软引用。
您阅读的文档比他们实际说的要多。在 VM 抛出 之前,将清除并释放所有可软访问的对象(这排除了它们是强可访问的)OutOfMemoryError
,但在最初确定它们为可软访问的点之后,VM 绝不需要保留它们。文档不禁止在发现它们可轻松访问的同一 GC 周期中回收它们。
但是,一般来说,您可以假设 GC 会优先处理幻像可达和弱可达对象。
我们将在哪里使用这些参考资料?哪个参考最适合实现缓存?
文档是这样说的:
软引用用于实现对内存敏感的缓存,弱引用用于实现不阻止其键(或值)被回收的规范化映射,幻影引用用于以比可能的更灵活的方式调度事前清理操作使用 Java 终结机制。
你继续问:
例如:如果我使用软引用进行缓存,那么当内存已满时它将被清除。但是让我们假设,我已经获取了一些数据库详细信息并将其放入内存中并将该详细信息缓存在软引用中,现在如果我从内存中删除了一些键值,它仍然会在缓存中。我们是否需要在此使用弱引用案例?应该如何做出决定。
如果您想构建一个可以丢弃其键不再可强访问的条目(这可能意味着无法再检索这些条目)的缓存,那么这正好处于弱引用的预期目的的中心。缓存在内部仅保存对每个条目的键的弱引用,并使用 a 注册这些引用,ReferenceQueue
让它知道何时应该丢弃它们。这正是WeakHashMap
工作原理。
如果您想构建一个可以通过丢弃条目来响应高内存需求的缓存,那么这就是软引用(对值)的预期目的;这种缓存的工作方式类似于WeakHashMap
,但使用对值的软引用而不是对键的弱引用。两者当然可以结合。
顺便提一下,Reference
对象只有在它们的所指对象不再是强可达时才与 GC 相关。特别是,拥有SoftReference
一个对象本身并不能保证该对象将被回收,无论对内存的需求是什么。任何可强可达的对象都不符合最终确定或回收的条件。
在大多数情况下,软引用用于缓存。您希望尽可能长时间地将数据保留在 RAM 中,但最好清除缓存而不是死于 OOM。
可以使用弱引用(例如)来保留有关您的班级的额外信息。您有课程User
并且想要存储一些附加信息,这些信息应该在删除用户时删除(您不想手动执行,因为它是样板代码)。因此,您使用WeakHashMap
usingUser
作为键,并且当没有对用户的引用时,它也会从该映射中删除。
顺便说一句:在具有引用计数的语言中,弱引用用于防止引用循环,但 java GC 删除了“隔离岛”,因此这种弱引用的用法不适用于 java。
如果您要实现自己的缓存,请使用软引用。
我曾经维护过一个遗留系统,它使用弱引用缓存来存储创建起来非常昂贵的大型对象。几乎每次一个线程试图从那个缓存中获取一个对象时,它已经被 GC'ed 了,所以这些对象不得不被大量地重新创建!这实际上就像缓存不存在。
但是让我们假设,我已经获取了一些数据库详细信息并将其放入内存中并将该详细信息缓存在软引用中,现在如果我从内存中删除了一些键值,它仍然会在缓存中。在这种情况下我们是否需要使用弱引用?应该如何做出决定。
我不确定我是否理解你的问题。当对这些细节的原始“硬”引用被 GC'ed 时,它仍然可以在软引用的缓存中。如果您从缓存中删除该项目,则根本没有更多对详细信息的引用,因此无论使用哪种引用指向它,它都会在下次被 GC 处理。
很少有 aWeakReference
有用的时候。请参阅弱引用 - 它们有多大用处?举一些例子
哪个参考最适合实现缓存?
对于缓存使用 SoftReference 类,缓存的全部意义在于保持它为快速使用做好准备 - 如果内存可用。因此,当内存不足 10 时,可以刷新缓存。
WeakReference 非常适合避免引用泄漏,当您有一些静态对象或线程保持对生命周期比该对象/线程短的对象的引用时,就会发生这种情况。我在 android 开发中使用了很多 WeakReference - s,尤其是 AsyncTask 的生命周期通常比创建它们的 Activity-s 生命周期长。
...在这种情况下我们需要使用弱引用吗?
一旦从缓存集合中删除此类条目,它将被垃圾收集,因此不需要 WeakReference。
我从未使用过 SoftReferences - 但那是因为我主要在 android 平台下编写代码,并且根据其文档http://developer.android.com/reference/java/lang/ref/SoftReference.html,它们对于缓存没有用 - 在至少在这个平台下。