上下文缓存,即将一些常用的数据至于一个缓存集合中,当需要获取这些数据的时候,直接从缓存中读取,而不必每次都从数据库读取,以此提高效率。

其原理类似Apache Commons Collections 项目中LRUMap,LRUMap它继承于AbstractLinkedMap 抽象类,其基本思想是将最近使用的数据放置于双向链表的头上,进行淘汰时只需要删除链表最后一个即可。

继承关系如下图:

从AbstractHashedMap看起,分析AbstractLinkedMap和LURMap。

1、AbstractHashedMap

AbstractHashedMap实现了Map接口,并自己单独实现了Hash算法,使自己成为一个HashedMap。

API介绍如下所示,我只拣几个重要属性和方法介绍一下

http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/map/AbstractHashedMap.html

2.1属性 protected  AbstractHashedMap.HashEntry[] data;

全局数组,每个数组的元素是一个带有后续指针(next)、key、hashcode、hashvalue的数据结构,可以说所有的操作都是为了维护这个数组

2.2属性 protected static int DEFAULT_CAPACITY 

默认的数组大小,可以通过构造函数指定

2.3属性 protected  float loadFactor 

扩展因子,默认为0.75,即数组填充率达到数组大小的75%的时候,会默认调整大小,重新计算元素在数组中的位置。

2.4方法 java.lang.Object get(java.lang.Object key) 

从data[]中与链表结构中取得value

2.5方法 java.lang.Object put(java.lang.Object key, java.lang.Object value) 

首先查看该value是否在data[]中,如果存在就更新一下就完事;否则就调用addMapping方法,生成一个新的HashEntry结构,加入到data[hashcode]对应位置的链表头上。在addMapping方法中,会检查容量是否超出了大小,如果查出了限制,则将容量扩大一倍,同时重新将所有数据塞进去。

2.6方法 java.lang.Object remove(java.lang.Object key) 

从维护的data结构中删除对应的value

2.7方法 protected  void reuseEntry(AbstractHashedMap.HashEntry entry, int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value) 

未研究

2.7其他方法,作用见名知意

protected void addEntry(AbstractHashedMap.HashEntry entry, int hashIndex)
protected void addMapping(int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value)
protected void removeEntry(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)
protected void removeMapping(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)

2、AbstractLinkedMap

AbstractLinkedMap继承自前面的AbstractHashedMap,在AbstractHashedMap的基础上,将所有的HashEntity维护成双向的链表

API地址如下:

http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/map/LinkedMap.html

3.1属性 protected AbstractLinkedMap.LinkEntry header

LinkEntry继承自HashEntry,又额外包含了before、after两个指针,形成双向链表
3.2方法 protected void addEntry(AbstractHashedMap.HashEntry entry, int hashIndex)

重写了父类的增加节点的方法,不但维护data[],同时维护了双向链表
3.3方法 protected void removeEntry(AbstractHashedMap.HashEntry entry, int hashIndex, AbstractHashedMap.HashEntry previous)

重写了父类的删除节点的方法,不但维护了data[],同时维护了双向链表

3、LRUMap

LRUMap也是非线程安全。主要是在父类AbstractLinedMap的基础上,在更新双向链表的时候增加了moveToMRU/removeLRU操作

4.1方法 protected  void moveToMRU(AbstractLinkedMap.LinkEntry entry) 

将entry移动到双向链表的头部

4.2方法 protected boolean removeLRU(AbstractLinkedMap.LinkEntry entry)

从双向链表中移除
4.3方法 protected void reuseMapping(AbstractLinkedMap.LinkEntry entry, int hashIndex, int hashCode, java.lang.Object key, java.lang.Object value)

重写父类的方法

4、扩展

利用LRUMap实现上下文缓存,可以对原有的LRUMap进行的改造点

(1)重写了LRUMAP类,采用synchronized关键字实现了线程级别安全。

(2)增加了对缓存数据容量的控制,超过容量之后,从双向链表中将最后使用的Entity从链表中删除。

(3)缓存数据的更新,采用异步通知机制,一旦受到更新通知,将变更的数据从换从中清除

参考:

http://annegu.iteye.com/blog/539465

http://www.blogjava.net/xmatthew/archive/2012/06/28/380150.html

利用LRUMap 设计缓存的更多相关文章

  1. 利用MVVM设计快速开发个人中心、设置等模块

    我们在做iOS开发过程中,静态页面的开发比开发动态页面更让我们开发者抓狂.因为动态页面通常是一个页面一种cell样式,作为开发者只需要专注于定制好一种样式之后,就可以使用数据填充出较好的界面.而静态c ...

  2. 利用PYTHON设计计算器功能

    通过利用PYTHON 设计处理计算器的功能如: 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 ))- (-4*3 ...

  3. 利用单例模式设计数据库连接Model类

    之前在<[php]利用php的构造函数与析构函数编写Mysql数据库查询类>(点击打开链接)写过的Mysql数据库查询类还不够完美,利用<[Java]单例模式>(点击打开链接) ...

  4. 【CPU微架构设计】利用Verilog设计基于饱和计数器和BTB的分支预测器

    在基于流水线(pipeline)的微处理器中,分支预测单元(Branch Predictor Unit)是一个重要的功能部件,它负责收集和分析分支/跳转指令的执行结果,当处理后续分支/跳转指令时,BP ...

  5. 2017-4-25/设计缓存(LFU)

    1. 恒定缓存性能有哪些因素? 命中率.缓存更新策略.缓存最大数据量. 命中率:指请求缓存次数和缓存返回正确结果次数的比例.比例越高,缓存的使用率越高,用来衡量缓存机智的好坏和效率.如果数据频繁更新, ...

  6. UE4笔记:利用Widget设计一个切换材质功能

    UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. ...

  7. iOS利用SDWebImage实现缓存的计算与清理

    概述 可以仅仅清理图片缓存, 也可以清理所有的缓存文件(包括图片.视频.音频等). 详细 代码下载:http://www.demodashi.com/demo/10717.html 一般我们项目中的缓 ...

  8. PyQt5系列教程(二)利用QtDesigner设计UI界面

    软硬件环境 OS X EI Capitan Python 3.5.1 PyQt 5.5.1 PyCharm 5.0.1 前言 在PyQt5系列教程的第一篇http://blog.csdn.net/dj ...

  9. 利用PowerDesigner设计数据库

    PowerDesigner非常强大, 可以利用它完成数据库的设计. 1.下载地址:http://pan.baidu.com/s/1DsLrg 2.表设计: 建立概念数据模型(Conceptual Da ...

随机推荐

  1. Struts2之异常处理

    一.学习案例:通过在input.jsp页面输入登录账号和password測试异常处理机制. 二.案例分析:struts2提供了局部异常处理机制和全局异常处理机制.局部优先于全局异常处理,当异常找不到局 ...

  2. codeigniter分页类传多个参数(转)

    http://example.com/index.php/控制器/方法名/页面的偏移值 页面的偏移值必须是方法名后第一个参数,否者分页类不能判断当前是哪一页,而用ci的分页类进行页面跳转时他是把偏移值 ...

  3. ActionScript 3 中的强制类型转换

    以前AS中是这样进行强制类型转换的:假设有一个类叫做Class1,我们声明了一个它的对象 c1,如果想要将它转换成Class2类型,只要这样写: Class2(c1); 在AS3中你依然可以这样写,但 ...

  4. BootStrap2学习日记13----关于按钮

    普通按钮 代码: <div style="margin-bottom:15px"> <a href="#" class="" ...

  5. [Java] HashMap、TreeMap、Hashtable排序

    Java中对Map(HashMap,TreeMap,Hashtable等)的排序时间 首先简单说一下他们之间的区别: HashMap: 最常用的Map,它根据键的HashCode 值存储数据,根据键可 ...

  6. Jsonp post 跨域方案

    近期在项目中遇到这样一问题,关于jsonp跨域问题,get传值是可以的,但post传值死活不行啊,于是网上看了一大堆关于这方面的资料,最终问题得以解决,今天抽空与大家分享下. 说明:http://ww ...

  7. linux注销开关机

    注销:exit 重启:reboot shutdown-r 表示延时分钟数   关机:halt shut -h  

  8. Linux下配置文件的位置

    系统级的配置存放在 /etc 目录中.用户级的配置存放在用户的主目录 /home/user_login_name. SHELL 默认文件 /etc/bashrc – bash shell 的系统级默认 ...

  9. IP地址计算和划分

    一.      B类地址 范围从128-191(第一串8位二进制10000000~10111111),如172.168.1.1,第一和第二段号码为网络号码,剩下的2段号码为本地计算机的号码.转换为2进 ...

  10. android图片切换ImageSwichter的动画切换效果

    activity_main.xml 控件的线性布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/an ...