LRU算法及java实现

一、算法原理
LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用与Linux操作系统。LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率也不大,因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据。
在这里插入图片描述

  1. 最开始时,内存空间是空的,因此依次进入A、B、C是没有问题的
  2. 当加入D时,就出现了问题,内存空间不够了,因此根据LRU算法,内存空间中A待的时间最为久远,选择A,将其淘汰
    当再次引用B时,内存空间中的B又处于活跃状态,而C则变成了内存空间中,近段时间最久未使用的
  3. 当再次向内存空间加入E时,这时内存空间又不足了,选择在内存空间中待的最久的C将其淘汰出内存,这时的内存空间存放的对象就是E->B->D
    二、应用场景
    1.CPU的高速缓存
    以目前最常见的L1、L2、L3为例:层数越往下,缓存越大,速度也越慢,cpu计算时经常要用到的数据会被从其他地方读到cache里。但cache的大小是有限的。当cpu想要读出一条cache里没有的数据时,势必需要淘汰一些存在cache里的数据来为新的数据腾出位置。这个时候按照什么原则去淘汰呢?一个很自然的想法就是:删掉那些cpu好久没用的数据吧!这就是LRU的策略
    2.Android中显示大量图片
    在你应用程序的UI界面加载一张图片是一件很简单的事情,但是当你需要在界面上加载一大堆图片的时候,情况就变得复杂起来。在很多情况下,(比如使用 ListView, GridView 或者 ViewPager 这样的组件),屏幕上显示的图片可以通过滑动屏幕等事件不断地增加,最终导致OOM。为 了保证内存的使用始终维持在一个合理的范围,通常会把被移除屏幕的图片进行回收处理。此时垃圾回收器也会认为你不再持有这些图片的引用,从而对这些图片进 行GC操作。用这种思路来解决问题是非常好的,可是为了能让程序快速运行,在界面上迅速地加载图片,你又必须要考虑到某些图片被回收之后,用户又将它重新滑入屏幕这种情况。这时,你可以使用LRU回收掉长时间不使用的图片,保留最近经常使用的图片,以此来维持图片内存在可控范围内。
    3.redis缓存淘汰
    当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
    三、技术实现
    Java中的LinkedHashMap实现了哈希双向链表,解决了哈希表Key-Value对无排列顺序的问题,像链条一样将Key-Value对串联起来,每一个Key-Value都有它的前驱Key-Value、后继Key-Value,使得哈希表拥有了固定的排列顺序,这一特性很好地和LRU算法的原理契合起来,是实现LRU算法的一种常用解决方案。
    在LinkedHashMap中可以保持两种顺序,分别是插入顺序和访问顺序,这个是可以在LinkedHashMap的初始化方法中进行指定的。相对于访问顺序,按照插入顺序进行编排被使用到的场景更多一些,所以默认是按照插入顺序进行编排。如果将构造函数中的accessOrder参数设置为true,即表示按访问顺序排序(也就是LRU了)。LinkedHashMap 继承自 HashMap,在 HashMap 基础上,通过维护一条双向链表,解决了 HashMap 不能随时保持遍历顺序和插入顺序一致的问题。
public class LRUMap<K,V> extends LinkedHashMap<K,V> {

    private int maxSize;

    public LRUMap(int maxSize){
        super(16,0.75f,true);
        this.maxSize=maxSize;
    }

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

    public static void main(String[] args) {
        LRUMap<String,Integer> test=new LRUMap<>(3);
        test.put("语文",128);
        test.put("数学",135);
        test.put("英语",120);
        test.put("理综",248);
        test.put("数学",125);
        test.put("语文",128);
        for (Map.Entry<String, Integer> entry : test.entrySet()) {
            System.out.println(entry.getKey()+" :"+entry.getValue());
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值