SoftReference在Map中的用法?

时间:2014-10-29 07:10:25

标签: java dictionary soft-references

我在遗留项目中看到下面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));

2 个答案:

答案 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以获取如何执行此操作的示例(顺便提一下参考密钥)。优点是,一旦你注意到软/弱的参考消失,你就可以摆脱任何剩余的强引用 然后,有trove4jApache Commons CollectionsGoldman Sachs ...