内存淘汰算法_java版linux内存淘汰算法LRU

    前边讲了很多有关linux系统的基础知识,今天我们来手动实现一下linux内存淘汰算法LRU算法。如下图便是我们之前讲过的,当linux内存不足时,需要将最不常用的页换出内存到swap分区,再从磁盘加载需要的内存进来。这里面其实包含着一种思想,时间局部性原理,当一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。    

739302e1b83c3aa73d1a826d452c24f3.png

    实现这种原理需要使用到数据结构中的链表。最新进入内存的页我们假设把它放到链表的尾部,每当中间某块内存被使用时,我们就把该内存移动到链表尾部,这样一来,链表头部就是最不常用的数据,而链表尾部则是最近使用的数据。这里的操作只需要一个头部指针和一个尾部指针,便可以实现复杂度为O(1)的操作。这是链表的优点

e798b294f1e4e775052219ccd88aa5f7.png

    可是我们怎么才能知道,哪一块内存最近被使用呢,如果我们采用标记节点,被使用的节点会被标记,那么我们每次都需要遍历整个列表,直到找到被标记的节点,然后进行节点移位操作,这个寻找过程就是一个O(n)的操作。所以我们必须要对这个步骤进行改善,那么如何改善才能使得我们可以快速定位到一块内存呢,其实也很容易想到计算机中常常使用的一个手段,那就是空间换取时间,维护一份数据结构呗,当你需要操作哪一块内存的时候,去这个数据结构中去查找,每当你操作完成后,更新这个数据结构。  维护的数据结构如下。

45e475bf3be7325041278b9d524adb59.png

    所以我们必须要对这个步骤进行改善,那么如何改善才能使得我们可以快速定位到一块内存呢,其实也很容易想到计算机中常常使用的一个手段,那就是空间换取时间,维护一份数据结构呗,当你需要操作哪一块内存的时候,去这个数据结构中去查找,每当你操作完成后,更新这个数据结构。  这里我们使用的当然是hash表这种根据key:value直接定位的数据结构。java中我们就是用HashMap。

f1f0e82497e11deeac736483b99ca8e7.png

    可是此处仍然会出现一个问题,当我们找到一个内存结点之后,将尾部指针指向该新节点,可是,接下来,我们需要将刚才内存的前驱节点和后继节点相连。由于我们的链表是单向的,所以,我们找不到该节点的前驱节点,只能又重新从头遍历,这又是O(n)的操作,所以一般都是hash表+双向链表的组合,也就是在节点数据结构中多维护一个指针。让每个节点知道自己前边是谁,后边是谁。最后我们就实现了O(1)操作进行内存淘汰。数据结构如下图所示

4af4cb58c7ea200b5274e417078d5ed5.png

    将数据load进内存,如果内存撑爆,开始淘汰头部节点。memoryMap为我们维护的hash表。

49e0e3e41a20a628aed9ee090c35b555.png

    从内存中获取一个内存块,则需要进行尾部更新,如下图

7d67d455a18e0b2137a4c156c99256ae.png

    测试结果如下所示。

290a70ff72b0344a6d2cfc0ca4dc68c4.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值