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

其原理类似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. ubuntu下tomcat启动巨慢分析

    在一个ubuntu14新环境部署tomcat,通过CI启动一个应用时,启动耗时达到15分钟之久.仔细看tomcat输出的耗时统计日志发现如下日志: Creation of SecureRandom i ...

  2. javascript数组总结(0504)

    一:数组复制 //方法一//slice()函数将会返回一个新的数组对象 var arr = [1,2,3,4]; var clone = arr.slice(0); arr.splice(1,2);/ ...

  3. android开发之路08(ListView&Adapter)

    ListView控件介绍:用于将数据库中的数据或者网络中的数据通过列表的形式显示出来:ListView采用MVC模式将前端显示和后端数据进行分离. 也就是说,ListView控件在装载数据时并不是直接 ...

  4. iOS 获取内存大小使用情况(进度条显示)

    一.获取设备内存大小方法 //返回存储内存占用比例 - (NSString *)getFreeDiskspaceRate{ float totalSpace; .f; NSError *error = ...

  5. [辛酸历程]在Mac中使用Python获取屏幕截图

    一.起因 最近想做个小外挂玩玩,技术倒是不难,就是通过图片匹配加上一些判断方法来刷分.但是在最不起眼(却最容易出问题)的准备阶段卡住了. 为什么卡住了呢,简单说,因为我需要获取截屏的数据,所以就要找一 ...

  6. ArcGIS Server 10.2 实战(五)spatial etl tool 格式转换服务

    上不同的地图服务平台对地图文件格式的要求多种多样,arcgis使用的文件很难应用于其他平台上,因此需要有格式转换的服务来克服这种使用不同平台带来的麻烦,下面以TIFF格式转GEOTIFF格式为例. 首 ...

  7. Mysql 复习

    1.my.ini :mysql 配置文件 [client]#password    = your_passwordport        = 3306socket        = /tmp/mysq ...

  8. Networking - ICMP 协议

    发送到远程计算机的数据通常发经过一个或多个路由器,这些路由器在把数据传输到最终目的地的过程中可能发生多种问题.路由器利用 ICMP 把问题通知给源 IP.ICMP 还有用于其他调试和排错的功能. IC ...

  9. HTTP - Cookie 机制

    HTTP 是种无状态的协议,即使用 HTTP 协议时,每次发送请求都会产生对应的新响应,协议本身不会保留之前一切的请求或响应报文的信息.这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTT ...

  10. Git CMD - add: Record changes to the repository

    命令格式 git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend] [--dry-run] [(-c ...