缓存算法(FIFO 、LRU、LFU三种算法的区别)
FIFO算法
FIFO 算法是一种比较容易实现的算法。它的思想是先进先出(FIFO,队列),这是最简单、最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小。空间满的时候,最先进入的数据会被最早置换(淘汰)掉。
FIFO 算法的描述:设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
- set(key,value):将记录(key,value)插入该结构。当缓存满时,将最先进入缓存的数据置换掉。
- get(key):返回key对应的value值。
实现:维护一个FIFO队列,按照时间顺序将各数据(已分配页面)链接起来组成队列,并将置换指针指向队列的队首。再进行置换时,只需把置换指针所指的数据(页面)顺次换出,并把新加入的数据插到队尾即可。
缺点:判断一个页面置换算法优劣的指标就是缺页率,而FIFO算法的一个显著的缺点是,在某些特定的时刻,缺页率反而会随着分配页面的增加而增加,这称为Belady现象。产生Belady现象现象的原因是,FIFO置换算法与进程访问内存的动态特征是不相容的,被置换的内存页面往往是被频繁访问的,或者没有给进程分配足够的页面,因此FIFO算法会使一些页面频繁地被替换和重新申请内存,从而导致缺页率增加。因此,现在不再使用FIFO算法。
LRU算法
LRU(The Least Recently Used,最近最久未使用算法)是一种常见的缓存算法,在很多分布式缓存系统(如Redis, Memcached)中都有广泛使用。
LRU算法的思想是:如果一个数据在最近一段时间没有被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最久没有访问的数据最先被置换(淘汰)。
LRU算法的描述: 设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
- set(key,value):将记录(key,value)插入该结构。当缓存满时,将最久未使用的数据置换掉。
- get(key):返回key对应的value值。
实现:最朴素的思想就是用数组+时间戳的方式,不过这样做效率较低。因此,我们可以用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构LinkedHashMap。
LInkedHashMap
利用Java的LinkedHashMap用非常简单的代码来实现基于LRU算法的Cache功能
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 简单用LinkedHashMap来实现的LRU算法的缓存
*/
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private int cacheSize;
public LRUCache(int cacheSize) {
super(16, (float) 0.75, true);
this.cacheSize = cacheSize;
}
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > cacheSize;
}
}
测试:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LRUCacheTest {
private static final Logger log = LoggerFactory.getLogger(LRUCacheTest.class);
private static LRUCache<String, Integer> cache = new LRUCache<>(10);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
cache.put("k" + i, i);
}
log.info("all cache :'{}'",cache);
cache.get("k3");
log.info("get k3 :'{}'", cache);
cache.get("k4");
log.info("get k4 :'{}'", cache);
cache.get("k4");
log.info("get k4 :'{}'", cache);
cache.put("k" + 10, 10);
log.info("After running the LRU algorithm cache :'{}'", cache);
}
}
Output:
all cache :'{k0=0, k1=1, k2=2, k3=3, k4=4, k5=5, k6=6, k7=7, k8=8, k9=9}'
get k3 :'{k0=0, k1=1, k2=2, k4=4, k5=5, k6=6, k7=7, k8=8, k9=9, k3=3}'
get k4 :'{k0=0, k1=1, k2=2, k5=5, k6=6, k7=7, k8=8, k9=9, k3=3, k4=4}'
get k4 :'{k0=0, k1=1, k2=2, k5=5, k6=6, k7=7, k8=8, k9=9, k3=3, k4=4}'
After running the LRU algorithm cache :'{k1=1, k2=2, k5=5, k6=6, k7=7, k8=8, k9=9, k3=3, k4=4, k10=10}'
LFU算法
LFU(Least Frequently Used ,最近最少使用算法)也是一种常见的缓存算法。
顾名思义,LFU算法的思想是:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰。
LFU 算法的描述:
设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:
- set(key,value):将记录(key,value)插入该结构。当缓存满时,将访问频率最低的数据置换掉。
- get(key):返回key对应的value值。
算法实现策略:考虑到 LFU 会淘汰访问频率最小的数据,我们需要一种合适的方法按大小顺序维护数据访问的频率。LFU 算法本质上可以看做是一个 top K 问题(K = 1),即选出频率最小的元素,因此我们很容易想到可以用二项堆来选择频率最小的元素,这样的实现比较高效。最终实现策略为小顶堆+哈希表。
参考:
Java集合详解5:深入理解LinkedHashMap和LRU缓存
缓存算法(FIFO 、LRU、LFU三种算法的区别)的更多相关文章
- FIFO 、LRU、LFU三种算法
提到缓存,有两点是必须要考虑的:(1)缓存数据和目标数据的一致性问题.(2)缓存的过期策略(机制). 其中,缓存的过期策略涉及淘汰算法.常用的淘汰算法有下面几种:(1)FIFO:First I ...
- 【算法集中营】CRC16 三种算法及c实现
标准CRC生成多项式如下表: 名称 生成多项式 简记式* 标准引用 CRC-4 x4+x+1 3 ...
- 最短路问题的三种算法&模板
最短路算法&模板 最短路问题是图论的基础问题.本篇随笔就图论中最短路问题进行剖析,讲解常用的三种最短路算法:Floyd算法.Dijkstra算法及SPFA算法,并给出三种算法的模板.流畅阅读本 ...
- c语言求回文数的三种算法的描述
c语言求回文数的三种算法的描述 题目描述 注意:(这些回文数都没有前导0) 1位的回文数有0,1,2,3,4,5,6,7,8,9 共10个: 2位的回文数有11,22,33,44,55,66,77,8 ...
- Java利用DES/3DES/AES这三种算法分别实现对称加密
转载地址:http://blog.csdn.net/smartbetter/article/details/54017759 有两句话是这么说的: 1)算法和数据结构就是编程的一个重要部分,你若失掉了 ...
- 浅析负载均衡的6种算法,Ngnix的5种算法。
浅析负载均衡的6种算法,Ngnix的5种算法.浮生偷闲百家号03-21 10:06关注内容导读其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果.源地址哈希的思想是根据获取客 ...
- ASP.NET缓存中Cache过期的三种策略
原文:ASP.NET缓存中Cache过期的三种策略 我们在页面上添加三个按钮并双击按钮创建事件处理方法,三个按钮使用不同的过期策略添加ASP.NET缓存. <asp:Button ID=&quo ...
- 链接属性rel=’external’、rel=’nofollow’、rel=’external nofollow’三种写法的区别
链接属性rel='external'.rel='nofollow'.rel='external nofollow'三种写法的区别 大家应该都知道rel='nofllow'的作用,它是告诉搜索引擎, ...
- <script>, <script async>, <script defer> 三种标签的区别
<script>, <script async>, <script defer> 三种标签的区别 <script>标签 阻塞html parsing 脚 ...
随机推荐
- 主机配置nginx后如何获取访问者IP
he你早的时候写了一个根据访问者ip查询天气的小接口,那时候还没得买域名,没有搞nginx,测试自然没有问题,然后随着一个小工具一块上线了,今天突然发现我的小工具有好几个人在使用了,就想写一个记录访问 ...
- Java编程基础篇第三章
逻辑运算符 与(&)(&&),或(||)(|),非(!) &和&&的区别 &:无论&的左边真假,右边都进行运算 &&:当 ...
- intput/output 文件的复制练习
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStrea ...
- 第k小整数
题目描述: 现有n个正整数,n≤10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k≤1000,正整数均小于30000. 输入: 第一行为n和k,第二行开始为n个正整数的值 ...
- Java新帮派——数组
一.什么是数组: 数组是一个变量,存储相同数据类型的一组数据 声明一个变量就是在内存空间划出一块合适的空间 声明一个数组就是在内存空间划出一串连续的空间 二.数组基本要素: 标识符:数组的名称,用于区 ...
- Maven常用的几个命令
mvn clean.mvn package:如果本地仓库中没有需要的jar,第一次执行命令的时候会从仓库下jar包 *) mvn clean :clean项目 *) mvn compile : 编译 ...
- LeetCode 788 Rotated Digits 解题报告
题目要求 X is a good number if after rotating each digit individually by 180 degrees, we get a valid num ...
- ES6 数值
数值的表示 二进制表示法新写法: 前缀 0b 或 0B . console.log(0b11 === 3); // true console.log(0B11 === 3); // true 八进制表 ...
- java框架之SpringBoot(4)-资源映射&thymeleaf
资源映射 静态资源映射 查看 SpringMVC 的自动配置类,里面有一个配置静态资源映射的方法: @Override public void addResourceHandlers(Resource ...
- java之数据库连接池-dbcp&c3p0&dbutils
介绍 因为数据库连接对象的创建比较消耗性能,所以可以在应用程序启动时就在内存中开辟一片空间(集合)存放多个数据库连接对象,后面需要连接时直接从该空间中取而不用新创建:使用完毕后归还连接(将连接重新放回 ...