Java缓存(LRU,FIFO)
创始人
2024-06-03 23:14:13
0

dc22fad5695f460cbb3127906f3e0b6b.gif现在软件或者网页的并发量越来越大了,大量请求直接操作数据库会对数据库造成很大的压力,处理大量连接和请求就会需要很长时间,但是实际中百分之80的数据是很少更改的,这样就可以引入缓存来进行读取,减少数据库的压力。

 

 

常用的缓存有Redis和memcached,但是有时候一些小场景就可以直接使用Java实现缓存,就可以满足这部分服务的需求。

 

缓存主要有LRU和FIFO,LRU是Least Recently Used的缩写,即最近最久未使用,FIFO就是先进先出,下面就使用Java来实现这两种缓存。

 

LRU

LRU缓存的思想

 

固定缓存大小,需要给缓存分配一个固定的大小。

每次读取缓存都会改变缓存的使用时间,将缓存的存在时间重新刷新。

需要在缓存满了后,将最近最久未使用的缓存删除,再添加最新的缓存。

按照如上思想,可以使用LinkedHashMap来实现LRU缓存。

 

这是LinkedHashMap的一个构造函数,传入的第三个参数accessOrder为true的时候,就按访问顺序对LinkedHashMap排序,为false的时候就按插入顺序,默认是为false的。

当把accessOrder设置为true后,就可以将最近访问的元素置于最前面,这样就可以满足上述的第二点。

 

/**

 * Constructs an empty LinkedHashMap instance with the

 * specified initial capacity, load factor and ordering mode.

 *

 * @param initialCapacity the initial capacity

 * @param loadFactor the load factor

 * @param accessOrder the ordering mode - true for

 * access-order, false for insertion-order

 * @throws IllegalArgumentException if the initial capacity is negative

 * or the load factor is nonpositive

 */

public LinkedHashMap(int initialCapacity,

                     float loadFactor,

                     boolean accessOrder) {

    super(initialCapacity, loadFactor);

    this.accessOrder = accessOrder;

}

这是LinkedHashMap中另外一个方法,当返回true的时候,就会remove其中最久的元素,可以通过重写这个方法来控制缓存元素的删除,当缓存满了后,就可以通过返回true删除最久未被使用的元素,达到LRU的要求。这样就可以满足上述第三点要求。

 

protected boolean removeEldestEntry(Map.Entry eldest) {

    return false;

}

由于LinkedHashMap是为自动扩容的,当table数组中元素大于Capacity * loadFactor的时候,就会自动进行两倍扩容。但是为了使缓存大小固定,就需要在初始化的时候传入容量大小和负载因子。

为了使得到达设置缓存大小不会进行自动扩容,需要将初始化的大小进行计算再传入,可以将初始化大小设置为(缓存大小 / loadFactor) + 1,这样就可以在元素数目达到缓存大小时,也不会进行扩容了。这样就解决了上述第一点问题。

 

通过上面分析,实现下面的代码

 

import java.util.LinkedHashMap;

import java.util.Map;

import java.util.Set;

 

public class LRU1 {

    private final int MAX_CACHE_SIZE;

    private final float DEFAULT_LOAD_FACTORY = 0.75f;

 

    LinkedHashMap map;

 

    public LRU1(int cacheSize) {

        MAX_CACHE_SIZE = cacheSize;

        int capacity = (int)Math.ceil(MAX_CACHE_SIZE / DEFAULT_LOAD_FACTORY) + 1;

        /*

         * 第三个参数设置为true,代表linkedlist按访问顺序排序,可作为LRU缓存

         * 第三个参数设置为false,代表按插入顺序排序,可作为FIFO缓存

         */

        map = new LinkedHashMap(capacity, DEFAULT_LOAD_FACTORY, true) {

            @Override

            protected boolean removeEldestEntry(Map.Entry eldest) {

                return size() > MAX_CACHE_SIZE;

            }

        };

    }

 

    public synchronized void put(K key, V value) {

        map.put(key, value);

    }

 

    public synchronized V get(K key) {

        return map.get(key);

    }

 

    public synchronized void remove(K key) {

        map.remove(key);

    }

 

    public synchronized Set> getAll() {

        return map.entrySet();

    }

 

    @Override

    public String toString() {

        StringBuilder stringBuilder = new StringBuilder();

        for (Map.Entry entry : map.entrySet()) {

            stringBuilder.append(String.format("%s: %s ", entry.getKey(), entry.getValue()));

        }

        return stringBuilder.toString();

    }

 

    public static void main(String[] args) {

        LRU1 lru1 = new LRU1<>(5);

        lru1.put(1, 1);

        lru1.put(2, 2);

        lru1.put(3, 3);

        System.out.println(lru1);

        lru1.get(1);

        System.out.println(lru1);

        lru1.put(4, 4);

        lru1.put(5, 5);

        lru1.put(6, 6);

        System.out.println(lru1);

    }

}

运行结果:

 

 

从运行结果中可以看出,实现了LRU缓存的思想。

 

接着使用HashMap和链表来实现LRU缓存。

 

主要的思想和上述基本一致,每次添加元素或者读取元素就将元素放置在链表的头,当缓存满了之后,就可以将尾结点元素删除,这样就实现了LRU缓存。

 

这种方法中是通过自己编写代码移动结点和删除结点,为了防止缓存大小超过限制,每次进行put的时候都会进行检查,若缓存满了则删除尾部元素。

 

import java.util.HashMap;

 

/**

 * 使用cache和链表实现缓存

 */

public class LRU2 {

    private final int MAX_CACHE_SIZE;

    private Entry head;

    private Entry tail;

 

    private HashMap> cache;

 

    public LRU2(int cacheSize) {

        MAX_CACHE_SIZE = cacheSize;

        cache = new HashMap<>();

    }

 

    public void put(K key, V value) {

        Entry entry = getEntry(key);

        if (entry == null) {

            if (cache.size() >= MAX_CACHE_SIZE) {

                cache.remove(tail.key);

                removeTail();

            }

            entry = new Entry<>();

            entry.key = key;

            entry.value = value;

            moveToHead(entry);

            cache.put(key, entry);

        } else {

            entry.value = value;

            moveToHead(entry);

        }

    }

 

    public V get(K key) {

        Entry entry = getEntry(key);

        if (entry == null) {

            return null;

        }

        moveToHead(entry);

        return entry.value;

    }

 

    public void remove(K key) {

        Entry entry = getEntry(key);

        if (entry != null) {

            if (entry == head) {

                Entry next = head.next;

                head.next = null;

                head = next;

                head.pre = null;

            } else if (entry == tail) {

                E

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...