我在遗留项目中看到了下面的 LRU 缓存实现,其中我对 SoftReference
的使用有疑问 适用于值对象,但不适用于键对象。
这里是实现
public class LRUCacheImpl<K, V> implements LRUCache<K, V> {
// SoftReference is used for a memory friendly cache.
// The value will be removed under memory shortage situations and
// the keys of the values will be removed from the cache map.
private final Map<K, SoftReference<V>> cache;
public LRUCacheImpl(final int cacheSize) {
// 'true' uses the access order instead of the insertion order.
this.cache = new LinkedHashMap<K, SoftReference<V>> (cacheSize, 0.75f, true) {
private static final long serialVersionUID = 1L;
@Override
protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) {
// When to remove the eldest entry i.e. Least Recently Used (i.e. LRU) entry
return size() > cacheSize; // Size exceeded the max allowed.
}
};
}
@Override
public V put(K key, V value) {
SoftReference<V> previousValueReference = cache.put(key, new SoftReference<V>(value));
return previousValueReference != null ? previousValueReference.get() : null;
}
@Override
public V get(K key) {
SoftReference<V> valueReference = cache.get(key);
return valueReference != null ? valueReference.get() : null;
}
}
如果应用程序即将达到内存不足 (OOM) 状态,GC 会回收软可达对象的内存。 如果我应用相同的逻辑,则仅应回收值的内存(因为仅为值对象创建软引用)。
但这是文件开头的注释
// SoftReference is used for a memory friendly cache. // The value will be removed under memory shortage situations and // the keys of the values will be removed from the cache map.
我的问题是,一旦应用程序达到 OOM,相应的关键对象将如何从 map 中删除。 key 不应该被包裹吗 也有软引用吗?
cache.put(new SoftReference<K>(key), new SoftReference<V>(value));
请您参考如下方法:
我不知道 LinkedHashMap
支持限制映射的大小。通过实现 removeEldestEntry
,您可以防止映射保存超过 cacheSize
键。
正如您在 LinkedHashMap
实现中所看到的,如果 removeEldestEntry
返回 true,添加新条目会导致删除最旧的条目。
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);
// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)
resize(2 * table.length);
}
}
因此,最近最少使用的键将从 map 中删除。
使用此构造函数:
this.cache = new LinkedHashMap<K, SoftReference<V>> (cacheSize, 0.75f, true)
表示条目按照其访问顺序排序。因此,每次获取或放置一个键时,都会将相应的条目移动到列表链表的后面,这意味着列表的开头包含最近最少使用的条目。
因此,//这些值的键将从缓存映射中删除
可能指的是最近最少使用的键最终将从映射中删除,与删除无关内存不足时的值。