LRU cache实现
来源:互联网 发布:淘宝网络客服招聘 编辑:程序博客网 时间:2024/05/01 22:31
引子:
我们平时总会有一个电话本记录所有朋友的电话,但是,如果有朋友经常联系,那些朋友的电话号码不用翻电话本我们也能记住,但是,如果长时间没有联系了,要再次联系那位朋友的时候,我们又不得不求助电话本,但是,通过电话本查找还是很费时间的。但是,我们大脑能够记住的东西是一定的,我们只能记住自己最熟悉的,而长时间不熟悉的自然就忘记了。
其实,计算机也用到了同样的一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力会有很大提高。但是,当我们读取的个数特别大的时候,我们不可能把所有已经读取的数据都放在缓存里,毕竟内存大小是一定的,我们一般把最近常读取的放在缓存里(相当于我们把最近联系的朋友的姓名和电话放在大脑里一样)。现在,我们就来研究这样一种缓存机制。
LRU Cache:
LRU缓存利用了这样的一种思想。LRU是Least Recently Used 的缩写,翻译过来就是“最不常使用”,也就是说,LRU缓存把最不常使用的数据移除,让给最新读取的数据。大多数情况下,最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance. LRU cache是非常频繁出现的一道面试题,一般来讲,当我们问到这道题时,面试官往往想得到的答案是利用 doubly linked list + hashtable 实现 LRU Cache, 那么我们现在就来讲一讲如何利用doubly linked list + hashtable实现LRU Cache的。
对于LRU cache,往往会有以下要求:
1. 假设Cache里面的 entry 都是按照序列保存的,那么,对于新的entry,我们把它放置在最前面。
2. 如果一个entry已经存在,我们再次访问到该entry的时候,我们需要把它放在cache的最前面。
3. 当cache满了的时候,需要把最后一个entry 从cache里面移除出去,然后再往里插入 entry。
4. 以上所有的操作复杂度必须为 O(1)。
对于操作复杂度,一旦看到要求为O(1), 一般我们都会立刻想到 hashtable, 所以,为了实现“顺序”的要求,我们需要有一个链表来连接所有的entry. 所以,在实现时,我们将Cache的所有 entry 都用doubly linked list 连接起来,当一个 entry 被命中之后,就将通过调整链表的指向,将该位置调整到链表头的位置,新加入的Cache直接加到链表头中。这样,在多次进行Cache操作后,最近被命中的,就会被向链表头方向移动,而没有命中的,而想链表后面移动,链表尾则表示最近最少使用的Cache。当需要替换内容时候,链表的最后位置就是最少被命中的位置,我们只需要淘汰链表最后的部分即可。
所谓LRU就是最近最少被使用的意思,LRUCache的目的就是当缓存中的数据量达到一定的程度时,添加新的数据会将最近最少被使用的旧数据删除,以保障Cache中的数据都是经常需要的数据,提高命中率。下面是一个基于linkedhashmap的LRUCache的简单实现,关键是重写LinkedHashMap的removeEldestEntry方法,在LinkedHashMap中该方法默认返回false(LRUCache本身未考虑线程安全的问题)
package test1;import java.util.LinkedHashMap;import java.util.Map;/** * Created by Administrator on 15-1-21. */public class BasicLRUCache<K, V> { private LinkedHashMap<K, V> map; private int cacheSize; static final int DEFAULT_CACHE_SIZE = 2; public BasicLRUCache(){ this(DEFAULT_CACHE_SIZE); } public BasicLRUCache(int cacheSize){ this.cacheSize = cacheSize; int hashTableSize = (int)Math.ceil(cacheSize/0.75f) + 1; map = new LinkedHashMap<K, V>(hashTableSize, 0.75f, true){ private static final long serialVersionUID = 1L; @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { System.out.println("size=" + size() + " cacheSize=" + BasicLRUCache.this.cacheSize); return size() > BasicLRUCache.this.cacheSize; } }; } public V put(K key, V value){ return map.put(key, value); } public V get(Object key){ return map.get(key); } public static void main(String[] args){ BasicLRUCache<String, String> lruCache = new BasicLRUCache<String, String>(3); lruCache.put("1", "1"); lruCache.put("2", "2"); lruCache.put("3", "3"); lruCache.put("4", "4"); System.out.println(lruCache.get("1")); System.out.println(lruCache.get("2")); System.out.println(lruCache.get("3")); System.out.println(lruCache.get("4")); }}
"C:\Program Files\Java\jdk1.7.0_67\bin\java" -Didea.launcher.port=7533 "-Didea.launcher.bin.path=D:\Program Files\JetBrains\IntelliJ IDEA 13.1.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_67\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\rt.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\access-bridge.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.7.0_67\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_67;D:\IdeaProject\test\dubbo-consumer;D:\IdeaProject\bppfRefactor\bpep-portal;D:\IdeaProject\bppfRefactor\test\target\classes;D:\Program Files\JetBrains\IntelliJ IDEA 13.1.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain test1.BasicLRUCachesize=1 cacheSize=3size=2 cacheSize=3size=3 cacheSize=3size=4 cacheSize=3null234Process finished with exit code 0
- LRU cache的实现
- LRU cache实现 (Java)
- [Google] LRU cache实现
- 实现LRU Cache
- 如何实现 LRU Cache?
- LRU Cache实现
- LRU Cache的实现
- LRU Cache 实现
- 简单LRU cache 实现
- LRU cache实现
- LRU cache实现 (Java)
- LRU cache实现
- LRU Cache的实现
- 如何实现 LRU Cache
- LRU Cache的实现
- LRU cache实现
- Python 实现LRU Cache
- 【链表】实现LRU缓存策略LRU Cache
- linux stat函数讲解
- 配置Apache2.x 支持shell脚本和Python编写CGI程序+测试程序
- sadkjsa d(4)
- ubuntu14.04下手动安装openstack juno版
- Java时间日期处理小结
- LRU cache实现
- 1223435345(5)
- 解决ie7和360不兼容的样式和js等问题。
- NSLayoutConstraint学习
- Android权限的介绍
- 理解HTTP session原理及应用
- 为应用做iOS8,iPhone6以及6plus的适配
- 快速办理学历真文凭QQ2585873282留学认证全套材料毕业证成绩单留学回国人员证明大使馆认证www.xhwpgs.com
- 微信JS-SDK 分享回调失效