Java实现LRU缓存的实例详解

1.Cache
Cache对于代码系统的加速与优化具有极大的作用,对于码农来说是一个很熟悉的概念。可以说,你在内存中new 了一个一段空间(比方说数组,list)存放一些冗余的结果数据,并利用这些数据完成了以空间换时间的优化目的,你就已经使用了cache。
有服务级的缓存框架,如memcache,Redis等。其实,很多时候,我们在自己同一个服务内,或者单个进程内也需要缓存,例如,lucene就对搜索做了缓存,而无须依赖外界。那么,我们如何实现我们自己的缓存?还要带自动失效的,最好还是LRU(Least Recently Used)。
当你思考怎么去实现,你可能会想得很远。为了LRU,需要把刚使用的数据存入栈,或者纪录每个数据最近使用的时间,再来的定时扫描失效的线程….其实,Java本身就已经为我们提供了LRU Cache很好的实现,即LinkedHashMap。
2.LinkedHashMap分析
很多没有去细究过其内部实现的人,只是将其当作一个普通的hashMap来对待。LinkedHashMap是一个双向链表,加上HashTable的实现。表现出来与普通HashMap的一个区别就是LinkedHashMap会记录存入其中的数据的顺序,并能按顺取出。
为了实现,一个hash表,自然应该先申请在一片连续的内存空间上。当需要存入数据的时候,根据相应的hash值存入。而LinkedHashMap在这个基础上,为每个entry设置了before与after属性,形了一个双向链表,记录了他们put进入的前后顺序。
不仅如此,每当通过get来获得某个元素后,get方法内部,会在最后通过afterNodeAccess方法来调整链表的指向:
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
上述代码将Node e移至了双向链表的未尾。而在方法afterNodeInsertion中,只要满足条件,便移除最老的数据,即链表的head。
void afterNodeInsertion(boolean evict) { // possibly remove eldest
LinkedHashMap.Entry<K,V> first;
if (evict && (first = head) != null && removeEldestEntry(first)) {
K key = first.key;
removeNode(hash(key), key, null, false, true);
}
}
可见,当你为LinkedHashMap设置有限空间的时候,自然便完成了LRU Cache的效果。当然还有一个前提,你必须重写一个方法removeEldestEntry,返回true。表示空间已满时,删除最老的。
@Override
public boolean removeEldestEntry(Map.Entry<K, V> eldest){
return size()>capacity;
}
3.线程安全的LRU Cache
如此,我们就获得了一个LRU缓存利器,满足了我们大多场景下的需求。但还有一个问题,它不是线程安全的。在多线程的情况下,你有可能需要对某些Cache做同步处理。这时候,你再找,可以看到java有ConcurrentHashMap的实现,但并不存在ConcurrentLinkedHashMap这样的类。
当然这个问题也不大,我们可以对再有的LinkedHashMap,再作封装,对get,put, 之类的方法加上同步操作。
目前,我们所用的处理,是直接采和google提供的guava包,这里面就提供了我们想要的ConcurrentLinkedHashMap。这样就可以很方便地实现一个线程安全。具体代码如下:
import java.util.Set;
import com.googlecode.concurrentlinkedhashmap.Weighers;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
public class ConcurrentLRUCache<K, V> {
public static final int DEFAULT_CONCURENCY_LEVEL = 32;
private final ConcurrentLinkedHashMap<K, V> map;
public ConcurrentLRUCache(int capacity) {
this(capacity, DEFAULT_CONCURENCY_LEVEL);
}
public ConcurrentLRUCache(int capacity, int concurrency) {
map = new ConcurrentLinkedHashMap.Builder<K, V>().weigher(Weighers.<V> singleton())
.initialCapacity(capacity).maximumWeightedCapacity(capacity)
.concurrencyLevel(concurrency).build();
}
public void put(K key, V value) {
map.put(key, value);
}
public V get(K key) {
V v = map.get(key);
return v;
}
public V getInternal(K key) {
return map.get(key);
}
public void remove(K key) {
map.remove(key);
}
public long getCapacity() {
return map.capacity();
}
public void updateCapacity(int capacity) {
map.setCapacity(capacity);
}
public int getSize() {
return map.size();
}
public void clear() {
map.clear();
}
public Set<K> getKeySet() {
return map.keySet();
}
}
以上就是Java实现LRU缓存的实例,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# Java
# LRU缓存
# LRU缓存的实例详解
# 详解Java
# Java 手写LRU缓存淘汰算法
# Java实现简单LRU缓存机制的方法
# 详解Java实现缓存(LRU
# FIFO)
# Java和Android的LRU缓存及实现原理
# Java资源缓存 之 LruCache
# 浅谈java如何实现Redis的LRU缓存机制
# 链表
# 是一个
# 当你
# 自己的
# 的人
# 最老
# 完成了
# 很好
# 你就
# 如有
# 可以说
# 你在
# 而在
# 会在
# 这个问题
# 将其
# 你有
# 我们可以
# 希望能
# 再来
相关文章:
全景视频制作网站有哪些,全景图怎么做成网页?
代购小票制作网站有哪些,购物小票的简要说明?
,柠檬视频怎样兑换vip?
Python lxml的etree和ElementTree有什么区别
如何高效完成独享虚拟主机建站?
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
导航网站建站方案与优化指南:一站式高效搭建技巧解析
建站VPS能否同时实现高效与安全翻墙?
建站主机如何安装配置?新手必看操作指南
制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?
如何零成本快速生成个人自助网站?
网页设计网站制作软件,microsoft office哪个可以创建网页?
网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?
如何使用Golang安装API文档生成工具_快速生成接口文档
如何在建站主机中优化服务器配置?
高端智能建站公司优选:品牌定制与SEO优化一站式服务
婚礼视频制作网站,学习*后期制作的网站有哪些?
建站主机选购指南:核心配置优化与品牌推荐方案
宝盒自助建站智能生成技巧:SEO优化与关键词设置指南
如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法
高端企业智能建站程序:SEO优化与响应式模板定制开发
深圳网站制作培训,深圳哪些招聘网站比较好?
如何设计高效校园网站?
企业微网站怎么做,公司网站和公众号有什么区别?
如何快速登录WAP自助建站平台?
html制作网站的步骤有哪些,iapp如何添加网页?
如何通过FTP服务器快速搭建网站?
Bpmn 2.0的XML文件怎么画流程图
,交易猫的商品怎么发布到网站上去?
如何访问已购建站主机并解决登录问题?
网站建设制作、微信公众号,公明人民医院怎么在网上预约?
官网自助建站平台指南:在线制作、快速建站与模板选择全解析
想学网站制作怎么学,建立一个网站要花费多少?
建站ABC备案流程中有哪些关键注意事项?
建站之星后台管理如何实现高效配置?
如何用美橙互联一键搭建多站合一网站?
广州营销型建站服务商推荐:技术优势与SEO优化解析
,如何利用word制作宣传手册?
深圳网站制作的公司有哪些,dido官方网站?
如何通过VPS建站无需域名直接访问?
,制作一个手机app网站要多少钱?
详解jQuery停止动画——stop()方法的使用
php json中文编码为null的解决办法
建站主机如何选?性能与价格怎样平衡?
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
一键网站制作软件,义乌购一件代发流程?
弹幕视频网站制作教程下载,弹幕视频网站是什么意思?
建站之星IIS配置教程:代码生成技巧与站点搭建指南
如何破解联通资金短缺导致的基站建设难题?
相亲简历制作网站推荐大全,新相亲大会主持人小萍萍资料?
*请认真填写需求信息,我们会在24小时内与您取得联系。