根据 Guava 的文档MapMaker.softValues()
:
警告:在大多数情况下,最好设置每个缓存的最大大小,而不是使用软引用。仅当您非常熟悉软引用的实际后果时,才应使用此方法。
我对软引用有一个中等的了解——它们的行为、用途以及它们与垃圾收集的约定。但是我想知道文档所暗示的这些实际后果是什么。为什么使用最大尺寸而不是软引用更好?在实现缓存方面,软引用的算法和行为是否比硬编码天花板更有效?
根据 Guava 的文档MapMaker.softValues()
:
警告:在大多数情况下,最好设置每个缓存的最大大小,而不是使用软引用。仅当您非常熟悉软引用的实际后果时,才应使用此方法。
我对软引用有一个中等的了解——它们的行为、用途以及它们与垃圾收集的约定。但是我想知道文档所暗示的这些实际后果是什么。为什么使用最大尺寸而不是软引用更好?在实现缓存方面,软引用的算法和行为是否比硬编码天花板更有效?
我认为他们也暗示的是,如果您使用软引用映射,您应该为最大的内存使用量和可能的更多 gc 活动做好准备,因为引用只是 gc'd,因为内存需要被释放。
如果您知道您只需要缓存中的最后 n 个值,那么使用 LRU 缓存是一种更精简的方法,对正在运行的应用程序具有更可预测的资源使用情况。
此外,据此,-server和 -client JVM 之间的行为似乎存在细微差别。
Sun JRE 对 SoftReference 的处理与 WeakReference 不同。如果可用内存没有压力,我们会尝试保留由 SoftReference 引用的对象。一个细节:“-client”和“-server”JRE 的策略是不同的:-client JRE 试图通过更喜欢清除 SoftReferences 而不是扩展堆来保持你的占用空间小,而 -server JRE 试图保持你的通过更喜欢扩展堆(如果可能)而不是清除 SoftReferences 来提高性能。一种尺寸并不适合所有人。
使用 SoftReference 的实际问题之一是它们往往会被一次性全部丢弃。您拥有缓存的原因是在大多数情况下提供相当好的性能。
但是,将 SoftReferences 用于缓存可能意味着在您的应用程序停止进行 GC 后,它将缓慢运行,直到重新构建缓存。即,就在您需要应用程序赶上的时候。
注意:您可以使用LinkedHashMap 作为 LRU 缓存,它不必很复杂。