缓存淘汰策略:
FIFO:先入先出策略
LFU:最少使用策略
LRU:最近最少使用策略
 
链表的数据结构:
可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可以是零散的。
常见的链表结构有:单链表,双向链表,循环链表等。
以单链表为例
每个节点除了存储数据以外,还要存储下一个节点地址,我们称之为后继指针。
头结点记录链表的基地址,尾节点的后继指针指向的是空地址null
循环链表:
双向链表:
双向循环链表:
 
双向链表插入,删除操作的时间复杂度是O(1)
单链表插入,删除操作的时间复杂度是O(n)
链表随机访问的时间复杂度是O(n)
 
注意:
单纯删除的时间复杂度是O(1),但往往删除前需要根据下标查找,时间复杂度为O(n)
针对删除操作与插入操作,由于单链表没有记录前驱节点位置,所以在删除与插入时,需要重新遍历链表,而双向链表则不需要。
java语言中,LinkedHashMap使用的就是双向链表。双向链表虽然比较耗费内存空间,但是性能更好,这是一种空间换时间的设计思想。
 
数组与链表各有利弊,数组对于缓存十分友好,且简单易用,缺点是数组是定长的,而容器如ArrayList,虽然支持动态扩容,但在扩容的时候需要重新分配空间且拷贝数据,十分损耗性能与内存。链表则会损耗更多的内存空间,并且会造成内存碎片,在java语言中,使用不当可能导致频繁的GC。
实际使用过程,应当根据场景选择使用数组还是链表。
 
使用链表实现LRU缓存淘汰算法:
使用单向链表存储缓存数据
缓存读取一个数据以后,遍历单向链表,有两种情况:
1.链表中已经存在,删除该数据,并且存储在链表头部
2.链表中不存在,又分为两种情况
    链表未满,直接插入到链表头部
    链表已满,删除尾部数据,将该数据存在链表头部
 
“数组简单易用,在实现上使用的是连续的内存空间,可以借助 CPU 的缓存机制,预读数组中的数据,所以访问效率更高。而链表在内存中并不是连续存储,所以对 CPU 缓存不友好,没办法有效预读。” 这里的CPU缓存机制指的是什么?为什么就数组更好了?
 
CPU在从内存读取数据的时候,会先把读取到的数据加载到CPU的缓存中。而CPU每次从内存读取数据并不是只读取那个特定要访问的地址,而是读取一个数据块(这个大小我不太确定)并保存到CPU缓存中,然后下次访问内存数据的时候就会先从CPU缓存开始查找,如果找到就不需要再从内存中取。这样就实现了比内存访问速度更快的机制,也就是CPU缓存存在的意义:为了弥补内存访问速度过慢与CPU执行速度快之间的差异而引入。
对于数组来说,存储空间是连续的,所以在加载某个下标的时候可以把以后的几个下标元素也加载到CPU缓存这样执行速度会快于存储空间不连续的链表存储。
Cache Line 是 Cache 与 DRAM 同步的最小单位. 典型的虚拟内存页面大小为 4KB,而典型的 Cache line 通常的大小为 32 或 64 字节
 
 

链表:如何实现LRU缓存淘汰算法?的更多相关文章

  1. 04 | 链表(上):如何实现LRU缓存淘汰算法?

    今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是+LRU+缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...

  2. 数据结构与算法之美 06 | 链表(上)-如何实现LRU缓存淘汰算法

    常见的缓存淘汰策略: 先进先出 FIFO 最少使用LFU(Least Frequently Used) 最近最少使用 LRU(Least Recently Used) 链表定义: 链表也是线性表的一种 ...

  3. 《数据结构与算法之美》 <04>链表(上):如何实现LRU缓存淘汰算法?

    今天我们来聊聊“链表(Linked list)”这个数据结构.学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是 LRU 缓存淘汰算法. 缓存是一种提高数据读取性能的技术 ...

  4. 链表(上):如何实现LRU缓存淘汰算法?

    一.什么是链表 和数组一样,链表也是一种线性表. 从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 链表中的每一个内存块被称为节点Node. ...

  5. Chapter 6 链表(上):如何实现LRU缓存淘汰算法?

    缓存淘汰策略: 一.什么是链表? 1.和数组一样,链表也是一种线性表. 2.从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的数据结构. 3.链表中的每 ...

  6. 详解工程师不可不会的LRU缓存淘汰算法

    大家好,欢迎大家来到算法数据结构专题,今天我们和大家聊一个非常常用的算法,叫做LRU. LRU的英文全称是Least Recently Used,也即最不经常使用.我们看着好像挺迷糊的,其实这个含义要 ...

  7. LRU缓存淘汰算法

    什么是LRU算法? LRU是Least Recently Used的缩写,即最近最少使用,在有限的内容块中存储最近使用次数最多的数据,当内容块已满时,把最少使用的数据删除以便存储新的内容.

  8. 昨天面试被问到的 缓存淘汰算法FIFO、LRU、LFU及Java实现

    缓存淘汰算法 在高并发.高性能的质量要求不断提高时,我们首先会想到的就是利用缓存予以应对. 第一次请求时把计算好的结果存放在缓存中,下次遇到同样的请求时,把之前保存在缓存中的数据直接拿来使用. 但是, ...

  9. 图解缓存淘汰算法二之LFU

    1.概念分析 LFU(Least Frequently Used)即最近最不常用.从名字上来分析,这是一个基于访问频率的算法.与LRU不同,LRU是基于时间的,会将时间上最不常访问的数据淘汰;LFU为 ...

随机推荐

  1. Java基础之增强for循环

    平时大家for循环应该用的不少,特别是增强for循环,简单快捷.但是在增强for中做删除操作,却会抛出java.util.ConcurrentModificationException,一起来看下. ...

  2. 【Aizu - 0525】Osenbei (dfs)

    -->Osenbei 直接写中文了 Descriptions: 给出n行m列的0.1矩阵,每次操作可以将任意一行或一列反转,即这一行或一列中0变为1,1变为0.问通过任意多次这样的变换,最多可以 ...

  3. 有趣的PHP一句话

    今天看到如下图所示的PHP一句话,觉得挺有意思. 代码如下: <?=~$_='$<>/'^'{{{{';echo $_;@${$_}[_](@${$_}[__]);?> 效果图 ...

  4. cogs 2320. [HZOI 2015]聪聪的世界题解

    2320. [HZOI 2015]聪聪的世界 时间限制:6 s   内存限制:512 MB [题目描述] 背景: 聪聪的性取向有问题. 题目描述: 聪聪遇到了一个难题: 给出一个序列a1…an,完成以 ...

  5. v8环境搭建采坑记录

    项目组有把js接入C++服务求的需求,故开始了v8接入的工作,用了一天多时间,v8才在centos环境上成功安装,过程中踩了很多坑,下面将采坑过程记录如下: centos下编译安装v8:   查看ce ...

  6. 当没有接口时、不可继承时,如果使用mock方案进行单元测试

    原版代码: import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; imp ...

  7. Single Thread Execution设计模式

    public class Test { public static void main(String[] args){ // FlightSercurityTest.test(); // EatNoo ...

  8. Lake Counting-C++

    Description Due to recent rains, water has pooled in various places in Farmer John's field, which is ...

  9. [原创]SSH Tunnel for UDP

    SSH Tunnel for UDP UDP port forwarding is a bit more complicated. We will need to convert the packet ...

  10. 细说Ansible主机清单inventory

    Ansible是一个系列文章,我会尽量以通俗易懂.诙谐幽默的总结方式给大家呈现这些枯燥的知识点,让学习变的有趣一些. Ansible系列博文直达链接:Ansible入门系列 前言 关于Ansible是 ...