【揭秘】如何使用LinkedHashMap来实现一个LUR缓存?

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

LRU(Least Recently Used)缓存是一种常用的缓存淘汰策略,用于在有限的缓存空间中存储数据。其基本思想是:如果数据最近被访问过,那么在未来它被访问的概率也更高。因此,LRU缓存会保留最近访问过的数据,并在缓存满时淘汰最久未使用的数据

定义

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

LRU(Least Recently Used)缓存是一种常用的缓存淘汰策略,用于在有限的缓存空间中存储数据,其基本思想是,如果数据最近被访问过,那么在未来它被访问的概率也更高,因此,LRU缓存会保留最近访问过的数据,并在缓存满时淘汰最久未使用的数据,代码实现思路如下:

  1. 插入新的数据项。
  2. 访问(或检索)现有的数据项,并将其标记为最近使用。
  3. 当缓存达到其容量限制时,删除最久未使用的数据项。

代码案例

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

为了演示LRU,使用LinkedHashMap类来实现一个LUR缓存,因为它内部已经处理了哈希表和双向链表,哈希表提供了快速的插入和查找操作(平均时间复杂度为O(1)),而双向链表则维护了元素的插入顺序或访问顺序(取决于构造函数的参数),代码如下:

import java.util.LinkedHashMap;  
import java.util.Map;  public class LRUCache<K, V> extends LinkedHashMap<K, V> {  private int cacheSize;  public LRUCache(int cacheSize) {  // 第三个参数设置为true表示应该按照访问顺序排序,最近访问的放在头部,最老访问的放在尾部  super(16, 0.75f, true); // 可以使用一个默认的初始容量,例如16  	this.cacheSize = cacheSize;  }  @Override  protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {  // 当map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据(即尾部的数据)  return size() > cacheSize;  }  
}

在上面的代码中,LRUCache类继承了LinkedHashMap并重写了removeEldestEntry方法,这个方法的默认实现总是返回false,意味着不会自动移除最老的条目,但是在实现中,当缓存的大小超过了指定的cacheSize时,该方法返回true,触发移除最久未使用的条目(也就是链表中的尾部元素)。

此外,通过将LinkedHashMap的构造函数中的accessOrder参数设置为true,让链表按照访问顺序来排序元素,这样,最近访问的元素会被放在链表的头部,而最久未访问的元素则会被放在尾部,当需要移除元素时,可以快速地移除链表尾部的元素。

这个设计思想利用了哈希表的高效查找和链表的顺序性来实现一个简单而有效的LRU缓存,通过重写一个方法,能够定制缓存的行为以符合LRU策略。

public static void main(String[] args) {  LRUCache<Integer, String> lruCache = new LRUCache<>(3);  lruCache.put(1, "one");    // 缓存是 {1="one"}  lruCache.put(2, "two");    // 缓存是 {1="one", 2="two"}  lruCache.put(3, "three");  // 缓存是 {1="one", 2="two", 3="three"}  lruCache.get(1);           // 最近访问的是1,缓存是 {2="two", 3="three", 1="one"}  lruCache.put(4, "four");   // 因为缓存容量只有3,所以移除最老的条目2,缓存变为 {3="three", 1="one", 4="four"}  
}

核心总结

【揭秘】如何使用LinkedHashMap来实现一个LUR缓存? - 程序员古德

使用LinkedHashMap实现LRU非常简单且高效,当业务比较简单、或者用来演示LRU的实现是没有啥问题的,它本身有一些限制,因此不适合用在线上,如下:

1、它不是线程安全的,如果多个线程同时访问这个LRU缓存,可能会导致数据不一致的问题,根本在于LinkedHashMap本身并不是线程安全的,所以在多线程环境下,需要额外的同步措施,比如使用Collections.synchronizedMap方法来包装这个缓存,或者在访问时加上同步块。

2、它没办法自动处理数据加载以及数据过期,在实际应用中,有时希望当缓存中不存在请求的数据时能够自动从数据库或其他数据源加载数据,或者当数据在一定时间内没有被访问时能够自动过期。

3、它没办法精准控制内存使用,虽然可以限制缓存中的条目数量,但是这个限制并不直接对应于内存使用量,不同的缓存条目可能占用不同大小的内存,所以这个简单的LRU缓存可能会导致内存溢出,尤其是在存储大对象时。

4、它很难扩展,由于这个实现是基于LinkedHashMap的,它的扩展性受到了一定的限制,如果需要更复杂的缓存行为或更高级的功能(比如缓存分区、备份、持久化等),它是做不到的。

关注我,每天学习互联网编程技术 - 程序员古德

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/314012.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NGUI基础-三大基础组件之Panel组件

目录 Panel组件 Panel的作用&#xff1a; 注意&#xff1a; 相关关键参数讲解&#xff1a; Alpha&#xff08;透明度值&#xff09;&#xff1a; Depth&#xff08;深度&#xff09;&#xff1a; Clippinng&#xff08;裁剪&#xff09;&#xff1a; ​编辑 None Tex…

Dockerfile - 工作流程、构建镜像、文件语法

目录 一、Dockerfile 1.1、简介 1.2、Dockerfile 构建镜像的流程 1.3、Dockerfile 文件语法 1.3.1、注意事项 1.3.2、FROM 1.3.3、MAINTAINER&#xff08;官方已废弃&#xff09; 1.3.4、RUN 1.3.5、EXPOSE 1.3.6、WORKDIR 1.3.7、ADD 和 COPY 1.3.8、ENV 1.3.9、…

前端 js 基础对象 (3)

js 对象定义 <!DOCTYPE html> <html> <body><h1>JavaScript 对象创建</h1><p id"demo1"></p> <p>new</p> <p id"demo"></p><script> // 创建对象&#xff1a; var persona {fi…

2024孙多勇®跨年演讲,重塑医美增长力,开启璀璨华章!

不谋万事者&#xff0c;不足谋一时&#xff1b;不谋全局者&#xff0c;不足谋一域。明者因时而变&#xff0c;智者随时而制。 12月31日-1月3日由汇成医美集团主办的&#xff0c;以“重塑医美增长力”为主题的第七届孙多勇跨年演讲暨「英雄2024」年度战略规划案&#xff0c;在中…

SELinux 安全模型——MLS

首发公号&#xff1a;Rand_cs BLP 模型&#xff1a;于1973年被提出&#xff0c;是一种模拟军事安全策略的计算机访问控制模型&#xff0c;它是最早也是最常用的一种多级访问控制模型&#xff0c;主要用于保证系统信息的机密性&#xff0c;是第一个严格形式化的安全模型 暂时无…

AI模型私人订制

使用AI可以把你的脸换成明星的脸&#xff0c;可以用于直播、录播。 AI换脸1 也可以把视频中明星的脸换成你的脸 AI换脸2 之所以能够替换成功&#xff0c;是因为我们有一个AI人物模型&#xff0c;AI驱动这个模型就可以在录制视频的时候替换指定人物的脸。AI模型从哪里来&…

SELinux 基本原理

本文讲述 SELinux 保护安全的基本原理 首发公号&#xff1a;Rand_cs 安全检查顺序 不废话&#xff0c;直接先来看张图 当我们执行系统调用的时候&#xff0c;会首先对某些错误情况进行检查&#xff0c;如果失败通常会得到一些 error 信息&#xff0c;通过查看全局变量 errno …

2.2 设计FMEA步骤二:结构分析

2.2.1 目的 设计结构分析的目的是将设计识别和分解为系统、子系统、组件和零件,以便进行技术风险分析。其主要目标包括: 可视化分析范围结构化表示:方块图、边界图、数字模型、实体零件识别设计接口、交互作用和间隙促进顾客和供应商工程团队之间的协作(接口责任)为功能分…

微服务(11)

目录 51.pod的重启策略是什么&#xff1f; 52.描述一下pod的生命周期有哪些状态&#xff1f; 53.创建一个pod的流程是什么&#xff1f; 54.删除一个Pod会发生什么事情&#xff1f; 55.k8s的Service是什么&#xff1f; 51.pod的重启策略是什么&#xff1f; 可以通过命令kub…

【熔断限流组件resilience4j和hystrix】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容起因resilience4j落地实现pom.xml依赖application.yml配置接口使用 hystrix 落地实现pom.xml依赖启动类上添加注解接口上使用 &#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟…

BLP模型

本篇文章是调研了许多资料后对 BLP 模型的一个总结 首发公号&#xff1a;Rand_cs MLS&#xff0c;Multi-level Security&#xff0c;主要关心的是数据机密性 D. Elliott Bell 和 Leonard J. LaPadula 在 1996 年提出了基本的 BLP 模型&#xff0c;主要有两个性质&#xff1a;…

【形式语言与自动机/编译原理】CFG-->Greibach-->NPDA(2)

本文将详细讲解《形式语言与自动机》&#xff08;研究生课程&#xff09;或《编译原理》&#xff08;本科生课程&#xff09;中的上下文无关文法&#xff08;CFG&#xff09;转换成Greibach范式&#xff0c;再转成下推自动机&#xff08;NPDA&#xff09;识别语言是否可以被接受…