LRU的实现思想

LRU表示Least Recently Used,即最近最少被使用的页面替换算法。其理论基础是局部性原理,也就是说最近被访问的对象将在不久以后再次被访问。

对于LRU算法,可以使用一个链表和hashmap来实现。链表中的节点表示缓存的页面,链表中的第一个元素就是要被替换的元素,所以替换的复杂度是O(1)。同时,还维护一个hashmap来建立访问对象和缓存页面的映射关系。

当需要访问某个对象时,先从hashmap中查看该对象是否在缓存中,如果在,则将该缓存页面从链表中取出并插入到链表尾部,并访问对象。否则,从链表头取出一个缓存页面,将要访问的对象写入该缓存并插入到链表尾部,并且在hashmap中更新该项。这样,所有最近被访问的页面总是处于链表的尾部,即表头的元素表示最近最少被使用的可替换的页面。

LRU的实现

在JDK1.5中,LinkedHashMap已经实现了LRU的功能,只需要根据需要重写removeEldestEntry就行了。LinkedHashMap维护着一个运行于所有条目的双向链表。有了这个双向链表,就可以在迭代的时候按照插入的顺序迭代出元素,或者通过LRU算法迭代元素。

在LinkedHashMap的构造方法中,你可以指定accessOrder参数,当其为true时,将按照LRU算法对entry进行遍历;当其为false时,按照插入的顺序进行遍历。其值默认为true。想要详细了解LinkedHashMap可参见 http://boy00fly.iteye.com/blog/1144691

这里贴一个使用LinkedHashMap实现LRU的线程安全的代码

http://www.iteye.com/topic/123856

import java.util.LinkedHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V>
{
    private final int maxCapacity;
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private final Lock lock = new ReentrantLock();

    public LRULinkedHashMap(int maxCapacity)
    {
        super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
        this.maxCapacity = maxCapacity;
    }

    @Override
    protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest)
    {
        return size() > maxCapacity;
    }

    @Override
    public V get(Object key)
    {
        try {
            lock.lock();
            return super.get(key);
        }
        finally {
            lock.unlock();
        }
    }

    @Override
    public V put(K key, V value)
    {
        try {
            lock.lock();
            return super.put(key, value);
        }
        finally {
            lock.unlock();
        }
    }
}
 

猜你喜欢

转载自eriol.iteye.com/blog/1165873