java - map 中软引用的用法?

标签 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;
 }
}

如果应用程序即将达到内存不足 (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)

表示条目按照其访问顺序排序。因此,每次获取或放置一个键时,都会将相应的条目移动到列表链表的后面,这意味着列表的开头包含最近最少使用的条目。

因此,//这些值的键将从缓存映射中删除可能指的是最近最少使用的键最终将从映射中删除,与删除无关内存不足时的值。

关于java - map 中软引用的用法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26624559/

相关文章:

java - 如何删除字符串中问号(?)后面的尾随字符?

python - 改变字典的所有键

java - Android上使用SoftReference缓存Bitmap导致OOM

java - Java 中的软引用 LinkedHashMap?

java - 从位于私有(private)方法中的变量读取

java.awt.color 返回颜色名称而不是 RGB 值

java - 在按下按钮之前,如何让我的按钮出现在随机位置?

dictionary - 可在 map 上观察以检测何时添加、更新或删除条目

python - 如何将 Python 字典存储为环境变量

java - 了解 Java 的引用类 : SoftReference, WeakReference 和 PhantomReference