FIFO算法

FIFO 算法是一种比较容易实现的算法。它的思想是先进先出(FIFO,队列),这是最简单、最公平的一种思想,即如果一个数据是最先进入的,那么可以认为在将来它被访问的可能性很小。空间满的时候,最先进入的数据会被最早置换(淘汰)掉

FIFO 算法的描述:设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:

  1. set(key,value):将记录(key,value)插入该结构。当缓存满时,将最先进入缓存的数据置换掉。
  2. get(key):返回key对应的value值。

实现:维护一个FIFO队列,按照时间顺序将各数据(已分配页面)链接起来组成队列,并将置换指针指向队列的队首。再进行置换时,只需把置换指针所指的数据(页面)顺次换出,并把新加入的数据插到队尾即可。

缺点:判断一个页面置换算法优劣的指标就是缺页率,而FIFO算法的一个显著的缺点是,在某些特定的时刻,缺页率反而会随着分配页面的增加而增加,这称为Belady现象。产生Belady现象现象的原因是,FIFO置换算法与进程访问内存的动态特征是不相容的,被置换的内存页面往往是被频繁访问的,或者没有给进程分配足够的页面,因此FIFO算法会使一些页面频繁地被替换和重新申请内存,从而导致缺页率增加。因此,现在不再使用FIFO算法

LRU算法

LRU(The Least Recently Used,最近最久未使用算法)是一种常见的缓存算法,在很多分布式缓存系统(如Redis, Memcached)中都有广泛使用。

LRU算法的思想是:如果一个数据在最近一段时间没有被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最久没有访问的数据最先被置换(淘汰)

LRU算法的描述: 设计一种缓存结构,该结构在构造时确定大小,假设大小为 K,并有两个功能:

  1. set(key,value):将记录(key,value)插入该结构。当缓存满时,将最久未使用的数据置换掉。
  2. get(key):返回key对应的value值。

实现:最朴素的思想就是用数组+时间戳的方式,不过这样做效率较低。因此,我们可以用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构LinkedHashMap

LInkedHashMap

利用JavaLinkedHashMap用非常简单的代码来实现基于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,并有两个功能:

  1. set(key,value):将记录(key,value)插入该结构。当缓存满时,将访问频率最低的数据置换掉。
  2. get(key):返回key对应的value值。

算法实现策略:考虑到 LFU 会淘汰访问频率最小的数据,我们需要一种合适的方法按大小顺序维护数据访问的频率。LFU 算法本质上可以看做是一个 top K 问题(K = 1),即选出频率最小的元素,因此我们很容易想到可以用二项堆来选择频率最小的元素,这样的实现比较高效。最终实现策略为小顶堆+哈希表。

参考:

缓存算法(页面置换算法)总结

谈谈缓存和基本的缓存算法

基于LinkedHashMap的LRUCache实现

Java集合详解5:深入理解LinkedHashMap和LRU缓存

缓存算法(FIFO 、LRU、LFU三种算法的区别)的更多相关文章

  1. FIFO 、LRU、LFU三种算法

    提到缓存,有两点是必须要考虑的:(1)缓存数据和目标数据的一致性问题.(2)缓存的过期策略(机制).     其中,缓存的过期策略涉及淘汰算法.常用的淘汰算法有下面几种:(1)FIFO:First I ...

  2. 【算法集中营】CRC16 三种算法及c实现

    标准CRC生成多项式如下表: 名称       生成多项式             简记式*  标准引用    CRC-4       x4+x+1                  3        ...

  3. 最短路问题的三种算法&模板

    最短路算法&模板 最短路问题是图论的基础问题.本篇随笔就图论中最短路问题进行剖析,讲解常用的三种最短路算法:Floyd算法.Dijkstra算法及SPFA算法,并给出三种算法的模板.流畅阅读本 ...

  4. c语言求回文数的三种算法的描述

    c语言求回文数的三种算法的描述 题目描述 注意:(这些回文数都没有前导0) 1位的回文数有0,1,2,3,4,5,6,7,8,9 共10个: 2位的回文数有11,22,33,44,55,66,77,8 ...

  5. Java利用DES/3DES/AES这三种算法分别实现对称加密

    转载地址:http://blog.csdn.net/smartbetter/article/details/54017759 有两句话是这么说的: 1)算法和数据结构就是编程的一个重要部分,你若失掉了 ...

  6. 浅析负载均衡的6种算法,Ngnix的5种算法。

    浅析负载均衡的6种算法,Ngnix的5种算法.浮生偷闲百家号03-21 10:06关注内容导读其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果.源地址哈希的思想是根据获取客 ...

  7. ASP.NET缓存中Cache过期的三种策略

    原文:ASP.NET缓存中Cache过期的三种策略 我们在页面上添加三个按钮并双击按钮创建事件处理方法,三个按钮使用不同的过期策略添加ASP.NET缓存. <asp:Button ID=&quo ...

  8. 链接属性rel=’external’、rel=’nofollow’、rel=’external nofollow’三种写法的区别

    链接属性rel='external'.rel='nofollow'.rel='external nofollow'三种写法的区别   大家应该都知道rel='nofllow'的作用,它是告诉搜索引擎, ...

  9. <script>, <script async>, <script defer> 三种标签的区别

    <script>, <script async>, <script defer> 三种标签的区别 <script>标签 阻塞html parsing 脚 ...

随机推荐

  1. vue2中使用transition

    最终效果为  div元素从右向左出现, 然后从左向右消失. transition标签包裹要移动的元素: css 样式: 其中: 1:  为div元素显示时的状态 2:  为div元素移动的过程 (进入 ...

  2. HTML中的清除浮动的常用方法(转载)

    以下面的div为例: HTML: <div class="test"> <div class="test1"></div> ...

  3. 对象copy的两种方式--序列化--clone

    对象实现copy有多中方式,最土的方法就是直接new,然后塞值,不过这种方法是真的low,下面着重说说Object类中的clone() 和 序列化反序列化copy Object 中 clone的方法 ...

  4. 利用python+selenium在pycharm下进行页面登陆的半自动测试

    很久没有写了,现在正式入职,准备好好干,加油! 我的第一个较正式的测试代码: from selenium import webdriverimport unittestimport sysimport ...

  5. 常用邮箱的 IMAP/POP3/SMTP 设置

    通过网上查找的资料和自己的总结完成了下面的文章,看完之后相信大家对这三种协议会有更深入的理解.如有错误的地方望指正. POP3 POP3是Post Office Protocol 3的简称,即邮局协议 ...

  6. da5_random模块

    import random #标准模块,用来取随机数 print(random.randint(1,100)) #随机取一个整数,顾头顾尾 print(random.uniform(1,900)) # ...

  7. jmeter将JDBC Request查询出的数据作为下一个接口的参数

    现在有一个需求,从数据库tieba_info表查出rank小于某个值的username和count(*),然后把所有查出来的username和count(*)作为参数值,用于下一个接口. tieba_ ...

  8. 减小ipa包大小

    1.删除不用的文件和图片 2.打release模式 3.色调单一图片采用8-bit的,对32-bit的图片采用压缩 4.对音视频采用aac压缩

  9. 合作开发工具——freeze和pipreqs

    以后在合作开发的过程中,难免会用到别人开发到一半或者将自己开发的项目交给别人,在转交项目的时候需要让别人知道本项目中用到了哪些模块,这时可以用到一条命令来帮助我们. pip3 freeze # 获取环 ...

  10. Java-idea-安装配置优化等

    1.属性配置 使用版本,winzip解压版,开发工具安装目录下idea.properties文件,自定义配置路径 # idea.config.path=${user.home}/.IntelliJId ...