基于 LinkedHashMap 实现LRU缓存调度算法原理

基于 LinkedHashMap 如何实现LRU缓存调度算法原理

LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉

Redis 内存淘汰机制 :
allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)

List:每次访问一个元素后把这个元素放在 List一端,这样一来最远使用的元素自然就被放到List的另一端。缓存满了的时候就把那最远使用的元素remove掉
但是List太慢,因为List底层是数组 , 要删掉的数据总是位于List底层数组的第一个位置,删掉之后,后面的数据要向前补位, 所以复杂度是O(n)

Map : 链表结构的 LinkedHashMapLinkedHashMap 默认的元素顺序是 put 的顺序,但是如果使用带参数的构造函数,那么 LinkedHashMap 会根据访问顺序来调整内部顺序。 LinkedHashMap的get()方法除了返回元素之外还可以把被访问的元素放到链表的底端,这样一来每次顶端的元素就是remove的元素。

仿照Redis 内存淘汰机制的原理,可以自己利用LinkedHashMap写一个LRU算法。

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author : cpucode
 * @date : 2021/5/23
 * @time : 16:26
 * @github : https://github.com/CPU-Code
 * @csdn : https://blog.csdn.net/qq_44226094
 */
public class UrlTest {
    
    
    public static void main(String[] args) {
    
    
        LinkedHashMap<String, String> map = createUrlMap();

        System.out.println("/*******************使用bb************************/");
        map.get("bb");
        System.out.println(map);

        System.out.println("/*******************使用aa************************/");
        map.get("aa");
        System.out.println(map);

        System.out.println();

        System.out.println("/*******************加入ee************************/");
        map.put("ee","55");
        System.out.println(map);

        System.out.println("/*******************加入ff************************/");
        map.put("ff","66");
        System.out.println(map);
    }

    static final int MAX_NUM = 5;

    public static LinkedHashMap<String, String> createUrlMap() {
    
    
        LinkedHashMap<String, String> map = null;

        /**
         * @param MAX_NUM  初始容量
         * @param 0.75F    加载因子,一般是 0.75f
         * @param true     false 基于插入顺序  true  基于访问顺序(get一个元素后,这个元素被加到最后,使用了LRU  最近最少被使用的调度算法)
         */
        map = new LinkedHashMap<String, String>(MAX_NUM,0.75F ,true){
    
    

            /**
             * 实现LRU的关键方法,如果map里面的元素个数大于了缓存最大容量,则删除链表的顶端元素
             *
             * @param var
             * @return
             */
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, String> var){
    
    
                return this.size() > MAX_NUM;
            }

        };

        map.put("aa", "11");
        map.put("bb", "22");
        map.put("cc", "33");
        map.put("dd", "44");

        System.out.println("/******************正常顺序************************/");
        System.out.println(map);
        System.out.println();

        return map;
    }
}

结果 :

/******************正常顺序************************/
{
    
    aa=11, bb=22, cc=33, dd=44}

/*******************使用bb************************/
{
    
    aa=11, cc=33, dd=44, bb=22}
/*******************使用aa************************/
{
    
    cc=33, dd=44, bb=22, aa=11}

/*******************加入ee************************/
{
    
    cc=33, dd=44, bb=22, aa=11, ee=55}
/*******************加入ff************************/
{
    
    dd=44, bb=22, aa=11, ee=55, ff=66}

猜你喜欢

转载自blog.csdn.net/qq_44226094/article/details/117197561