弱引用允许GC在下一个GC周期中收集引用,而软引用将保留引用,直到内存已满,并且在抛出内存错误之前,它将删除软引用。我们将在哪里使用这些引用?哪个引用最适合实现缓存?例如:如果我使用软引用进行缓存,那么当内存满的时候它就会被清除。但让我们假设,我已经获取了一些数据库细节,并将其放在内存中,并在软引用中缓存了该细节,现在如果我从内存中删除了一些键值,它仍然在cache.Do中。在这种情况下,我们需要使用弱引用吗?应该如何做出决定。
发布于 2015-09-08 02:00:01
在大多数情况下,软引用用于缓存。您希望尽可能长时间地将数据保留在RAM中,但清除缓存比使用OOM更好。
弱引用可以(例如)用来保存有关类的额外信息。你有User类,你想存储一些额外的信息,这些信息应该在删除用户时删除(你不想手动删除,因为它是bolierplate代码)。因此,您使用使用User作为键的WeakHashMap,并且当没有对用户的引用时,它也将从该映射中删除。
顺便说一句:在有引用计数的语言中,弱引用是用来防止引用循环的,但java GC消除了“隔离岛”,所以弱引用的这种用法不适用于java。
发布于 2015-09-08 03:18:42
弱引用允许GC在下一个GC周期中收集引用,而软引用将保留引用,直到内存已满,在抛出内存错误之前,它将删除软引用。
你从文档中读到的比他们实际说的要多。在VM抛出OutOfMemoryError之前,将清理并释放所有软可达的对象(这排除了它们是强可达的),但VM绝不需要在它们最初被确定为软可达之前保留它们。文档并不禁止在相同的GC周期中回收它们,在同一GC周期中,它们被发现是软可达的。
但是,一般来说,您可以假设GC将优先处理幻影可达对象和弱可达对象。
我们将在哪里使用这些引用?哪个引用最适合实现缓存?
The docs这样说:
软引用用于实现内存敏感的缓存,弱引用用于实现不会阻止其键(或值)被回收的规范化映射,而幻影引用用于以比Java finalization机制更灵活的方式调度事前清理操作。
你可以继续问:
For eg:如果我使用软引用进行缓存,那么当内存满的时候它就会被清除。但让我们假设,我已经获取了一些数据库细节,并将其放在内存中,并在软引用中缓存了该细节,现在如果我从内存中删除了一些键值,它仍然在cache.Do中。在这种情况下,我们需要使用弱引用吗?应该如何做出决定。
如果您想要构建一个可以丢弃其键不再是强可达的条目(这可能意味着这些条目不再能够被检索)的缓存,那么它正好处于弱引用的预期用途的中心。缓存在内部只保存对每个条目的键的弱引用,并将这些引用注册到一个ReferenceQueue,让它知道何时应该丢弃这些引用。这正是WeakHashMap的工作原理。
如果您希望构建一个可以通过丢弃条目来响应高内存需求的缓存,那么这就是软引用(对值)的预期目的;这种缓存的工作方式类似于WeakHashMap,但使用的是对值的软引用,而不是对键的弱引用。当然,这两者可以结合在一起。
请注意,顺便说一句,只有当Reference对象的引用对象不再是强可及时,它们才与GC相关。特别是,拥有对象的SoftReference本身并不能保证该对象将被回收,无论对内存的需求是什么。任何一个强可达的对象都不符合终止或回收的条件。
发布于 2015-09-08 01:54:08
如果您正在实现自己的缓存,请使用软引用。
我曾经维护过一个遗留系统,该系统使用弱引用缓存来存储创建成本非常高的大型对象。几乎每次线程试图从该缓存中获取一个对象时,它都已经被GC了,所以这些对象必须大量地重新创建!实际上就像缓存不在那里一样。
,但让我们假设,我已经获取了一些数据库细节,并将其放在内存中,并在软引用中缓存了该细节,现在如果我从内存中删除了一些键值,它仍将在缓存中。在这种情况下,我们需要使用弱引用吗?应该如何做出决定。
我不太明白你的问题。当对这些细节的原始“硬”引用被GC时,它仍然可以在软引用的缓存中。如果从缓存中删除该项,则不再有对详细信息的引用,因此无论使用哪种类型的引用指向它,下次都会对其进行GC。
在极少数情况下,WeakReference是有用的。有关示例,请参阅Weak references - how useful are they?
https://stackoverflow.com/questions/32443746
复制相似问题