我在遗留项目中看到下面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;
}
}
如果应用程序即将到达OutOfMemory(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,将如何从地图中删除相应的关键对象。钥匙不应该被包裹 还有软参考?
cache.put(new SoftReference<K>(key), new SoftReference<V>(value));
答案 0 :(得分:2)
我不知道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);
}
}
因此,最近最少使用的密钥将从地图中删除。
使用此构造函数:
this.cache = new LinkedHashMap<K, SoftReference<V>> (cacheSize, 0.75f, true)
表示根据访问顺序对条目进行排序。因此,每次获取或放置密钥时,都会将相应的条目移动到列表链接列表的后面,这意味着列表的开头包含最近最少使用的条目。
因此,//the keys of the values will be removed from the cache map
可能指的是最近最少使用的密钥最终将从地图中删除的事实,与内存不足时删除值无关。
答案 1 :(得分:0)
如果错综复杂,可以选择SELECT price as total FROM yourtable WHERE from = 30 AND to = 33
中的换行符。
我们的目标是避免使用OOM,同时不会产生任何缺点,以免从缓存中获取值,以便不必要地放弃它们。
仅仅在Reference
中包装密钥对于标准的Map实现是不够的 -
在不覆盖Reference
&amp; equals()
的情况下,没有任何键看起来是平等的:没有找到,替换,删除,...
另一种方法是将hashCode()
与Soft/WeakReference
s一起使用:请参阅Map.Entry
以获取如何执行此操作的示例(顺便提一下参考密钥)。优点是,一旦你注意到软/弱的参考消失,你就可以摆脱任何剩余的强引用
然后,有trove4j,Apache Commons Collections,Goldman Sachs ...