Java中的LRU缓存实现

时间:2015-05-08 17:54:46

标签: java multithreading caching concurrency lru

我已经看到了以下代码,我认为在addElement方法的实现中有一个无用的while循环。它应该永远不会出现比size + 1更多的元素,因为已经存在写锁定。 那么为什么addElement方法删除元素直到它获得这个条件 真

while(concurrentLinkedQueue.size() >=maxSize)

任何针对此的指针都会很棒。

以下是实施:

public class  LRUCache<K,V> {

    private  ConcurrentLinkedQueue<K> concurrentLinkedQueue = new ConcurrentLinkedQueue<K>();

    private  ConcurrentHashMap<K,V> concurrentHashMap = new ConcurrentHashMap<K, V>();

    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private Lock readLock = readWriteLock.readLock();

    private Lock writeLock = readWriteLock.writeLock();

    int maxSize=0;

    public LRUCache(final int MAX_SIZE){
        this.maxSize=MAX_SIZE;
    }

    public V getElement(K key){

        readLock.lock();
        try {
        V v=null;
          if(concurrentHashMap.contains(key)){
              concurrentLinkedQueue.remove(key);
              v= concurrentHashMap.get(key);
                concurrentLinkedQueue.add(key);
          }


        return v;
        }finally{
            readLock.unlock();
        }
    }

    public V removeElement(K key){
         writeLock.lock();
         try {
        V v=null;
        if(concurrentHashMap.contains(key)){
        v=concurrentHashMap.remove(key);
            concurrentLinkedQueue.remove(key);
        }

        return v;
         } finally {
             writeLock.unlock();
         }
    }

    public V addElement(K key,V value){
        writeLock.lock();
        try {
        if(concurrentHashMap.contains(key)){
             concurrentLinkedQueue.remove(key);
        }
        while(concurrentLinkedQueue.size() >=maxSize){
             K queueKey=concurrentLinkedQueue.poll();
             concurrentHashMap.remove(queueKey);
        }
        concurrentLinkedQueue.add(key);
        concurrentHashMap.put(key, value);

        return value;
        } finally{
            writeLock.unlock();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

这里的观点是,我想,你需要检查LRU是否达到它的最大尺寸。这里的检查不是(map.size()&gt; maxSize),它是“&gt; =”。现在,您可以使用“if(map.size()== maxSize){...}”替换它 - 在理想条件下,它应该完全相同。

但是在不太理想的条件下,如果出于某种原因,有人在地图中放置了EXTRA条目而没有检查,那么使用此代码,地图将永远不会再次缩小,因为if条件永远不会真。

所以 - 为什么不“while”和“&gt; =”而不是“if”和“==”?相同数量的代码,以及对“意外”条件的更强大。

答案 1 :(得分:0)

LRU缓存的简单实现如下所示,while循环仅在调整max size时需要,但不适用于原始操作:

  • 在放置过程中,移除超级元素。
  • 在get期间,将元素移到顶部。

原始操作将是一次性的。然后,您可以在此数据结构周围使用普通的同步或读写锁。

当使用读写锁定时,对谁来说是公平性的,而不是LRU缓存本身使用的读写锁定的问题。

Here是一个示例实现。

答案 2 :(得分:0)

这没错,只是在意外修改的情况下确保安全。您可以在条件语句中检查是否与concurrentLinkedQueue.size() == maxSize相等。