CacheManager类
使用一个HashMap来缓存从数据库中查询出的Object,并提供获取,存放,清除的方法
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : CacheManager.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.util;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
class CostComparator implements Comparator {
public int compare(Object o1, Object o2) {
return ((Double) o1).compareTo((Double) o2);
}
public boolean equals(Object o) {
return super.equals(o);
}
}
public class CacheManager {
//三种清除cache时的排序策略
public static int LRU = 0;
public static int LFU = 1;
public static int MIX = 2;
//使用一个HashMap来存储Object
private HashMap cacheHashMap = new HashMap();
private int CACHE_CAPACITY = 100;
private int TRESHOLD = 90;
private int purgeAlgorithm;
private long hitCount = 0;
private long missCount = 0;
public CacheManager(int purgeAlgorithm, int cacheCapacity, int treshold) {
this.purgeAlgorithm = purgeAlgorithm;
CACHE_CAPACITY = cacheCapacity;
TRESHOLD = treshold;
}
public CacheManager(int purgeAlgorithm) {
this.purgeAlgorithm = purgeAlgorithm;
}
/**
*根据字符串identifier从cacheHashMap容器中获取cachedObject对象
*如果cacheHashMap中没有identifier键,或cachedObject已经过时,则返回null,
*同时missCount值加1
*否则获取对应的cachedObject对象,并使hitCount加1
*/
public synchronized Object getCache(String identifier) {
CachedObject cachedObject = (CachedObject) cacheHashMap.get(identifier);
Object obj = null;
if (cachedObject == null) {
missCount++;
} else if (cachedObject.isExpired()) {
cacheHashMap.remove(identifier);
missCount++;
} else {
cachedObject.incNumAccess();
cachedObject.setLastAccessTime(new Date());
hitCount++;
obj = cachedObject.getObject();
}
return obj;
}
public synchronized void invalidate(String identifier) {
cacheHashMap.remove(identifier);
}
public long getHitCount() {
return hitCount;
}
public long getMissCount() {
return missCount;
}
public long getCurrentCacheSize() {
return cacheHashMap.size();
}
public synchronized void putCache(Object object, String id,
int minutesToLive) {
CachedObject cachedObject = new CachedObject(object, id, minutesToLive);
if (cacheHashMap.size() == CACHE_CAPACITY) {
sweep();
}
cacheHashMap.put(id, cachedObject);
}
/**
*cacheHashMap容器的整理
*先将超时的cachedObject清除,
*当cachedObject数量大于TRESHOLD时,将访问频率小(次数小)的cachedObject清除
*/
public synchronized void sweep() {
TreeMap costTreeMap = new TreeMap(new CostComparator());
for (Iterator i = cacheHashMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
CachedObject cachedObject = (CachedObject) entry.getValue();
if (cachedObject.isExpired()) {
cacheHashMap.remove(entry.getKey());
} else {
double cost = 0.0;
switch (purgeAlgorithm) {
case 0:
cost = cachedObject.getLFUCost();
break;
case 1:
cost = cachedObject.getLRUCost();
break;
default:
cost = cachedObject.getMixCost();
}
costTreeMap.put(new Double(cost), entry.getKey());
}
}
// delete to treshold
for (int i = cacheHashMap.size(); i > TRESHOLD; i--) {
Object kk = costTreeMap.firstKey();
Object k = costTreeMap.get(kk);
cacheHashMap.remove(k);
costTreeMap.remove(kk);
}
}
public void clearCache() {
hitCount = 0;
missCount = 0;
cacheHashMap.clear();
}
/**
*将字符数组生成形如:"keys1/keys2/keys3"的字符串
*/
public static String createKey(String[] keys) {
StringBuffer newKey = new StringBuffer("");
for (int i = 0; i < keys.length; i++)
newKey.append(keys[i]).append("/");
return newKey.toString();
}
}
//==============================
DAOCacheManager类
持有一个静态的CacheManager类对象,提供对其的操作方法
业务方法都要通过他来使用cacheManager
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : DAOCacheManager.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.dao;
import java.text.MessageFormat;
import net.cn37signals.company.util.CacheManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class DAOCacheManager {
private static Log log = LogFactory.getFactory().getInstance("DAOCacheManager");
//cacheManager是静态的,供多个线程公用
private static CacheManager cacheManager = new CacheManager(CacheManager.MIX);
/**
*从cache中获取对象
*/
public static Object getCache(String identifier) {
if (log.isInfoEnabled()) {
Object[] o = {new Long(cacheManager.getHitCount()), new Long(cacheManager.getMissCount())};
log.info(MessageFormat.format(" [DAOCacheManager] getCache: {0} hits, {1} misses", o));
}
return cacheManager.getCache(identifier);
}
/**
*将对象放入cache中
*/
public static void putCache(Object object, String id, int minutesToLive) {
if (log.isInfoEnabled()) {
log.info(" [DAOCacheManager] putCache");
}
cacheManager.putCache(object, id, minutesToLive);
}
public static void invalidate(String id) {
cacheManager.invalidate(id);
}
}
//=====================
CachedObject类
对要放入cache的对象进行包装
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : CachedObject.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.util;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class CachedObject {
public Object object = null;
private Date dateofExpiration = null;
private String identifier = null;
private Date lastAccessTime = new Date();
private long numAccess = 1;
private int size;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public CachedObject(Object obj, String id, int minutesToLive) {
this.object = obj;
this.identifier = id;
size = objectSize(obj);
lastAccessTime = new Date();
// minutesToLive of 0 means it lives on indefinitely.
if (minutesToLive != 0) {
Calendar cal = Calendar.getInstance();
cal.setTime(lastAccessTime);
cal.add(cal.MINUTE, minutesToLive);
dateofExpiration = cal.getTime();
}
}
public void setLastAccessTime(Date lastAccessTime) {
this.lastAccessTime = lastAccessTime;
}
public boolean isExpired() {
// Remember if the minutes to live is zero then it lives forever!
if (dateofExpiration != null && dateofExpiration.before(new Date())) {
return true;
}
return false;
}
public String getIdentifier() {
return identifier;
}
public Object getObject() {
return object;
}
public Date getDateofExpiration() {
return (this.dateofExpiration);
}
public Date getLastAccessTime() {
return (this.lastAccessTime);
}
public long getNumAccess() {
return (this.numAccess);
}
public long getSize() {
return (this.size);
}
public double getMixCost() {
long milis = new Date().getTime() - lastAccessTime.getTime();
if(milis == 0) {
milis = 1;
}
return (double)numAccess / (double)milis / (double)size;
}
public double getLRUCost() {
long milis = new Date().getTime() - lastAccessTime.getTime();
if(milis == 0) {
milis = 1;
}
return 1.0/(double)milis;
}
public double getLFUCost() {
return (double) numAccess;
}
public void incNumAccess() {
numAccess++;
}
public boolean equals(Object o2) {
try {
String key2 = ((CachedObject) o2).getIdentifier();
return identifier.equals(key2);
} catch (Exception e) {
return false;
}
}
private static int objectSize(Object o) {
try {
int size = ((List) o).size();
return size + 1;
} catch (Exception e) {
return 1;
}
}
}
//==============================
使用方法
public List list(int offset, int limit) throws SQLException {
String[] objKeys = {"Users", "list", String.valueOf(offset), String.valueOf(limit)};
String objKey = CacheManager.createKey(objKeys);
ArrayList list = (ArrayList) DAOCacheManager.getCache(objKey);
//如果cache的hashmap中有,直接取出,没有则从数据库中查询,并放入hashmap中
if (list != null)
return list;
//--
//从数据库中查询(略)
//--
//将查询结果放入cache
DAOCacheManager.putCache(list, objKey, 1);
return list;
}
使用一个HashMap来缓存从数据库中查询出的Object,并提供获取,存放,清除的方法
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : CacheManager.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.util;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
class CostComparator implements Comparator {
public int compare(Object o1, Object o2) {
return ((Double) o1).compareTo((Double) o2);
}
public boolean equals(Object o) {
return super.equals(o);
}
}
public class CacheManager {
//三种清除cache时的排序策略
public static int LRU = 0;
public static int LFU = 1;
public static int MIX = 2;
//使用一个HashMap来存储Object
private HashMap cacheHashMap = new HashMap();
private int CACHE_CAPACITY = 100;
private int TRESHOLD = 90;
private int purgeAlgorithm;
private long hitCount = 0;
private long missCount = 0;
public CacheManager(int purgeAlgorithm, int cacheCapacity, int treshold) {
this.purgeAlgorithm = purgeAlgorithm;
CACHE_CAPACITY = cacheCapacity;
TRESHOLD = treshold;
}
public CacheManager(int purgeAlgorithm) {
this.purgeAlgorithm = purgeAlgorithm;
}
/**
*根据字符串identifier从cacheHashMap容器中获取cachedObject对象
*如果cacheHashMap中没有identifier键,或cachedObject已经过时,则返回null,
*同时missCount值加1
*否则获取对应的cachedObject对象,并使hitCount加1
*/
public synchronized Object getCache(String identifier) {
CachedObject cachedObject = (CachedObject) cacheHashMap.get(identifier);
Object obj = null;
if (cachedObject == null) {
missCount++;
} else if (cachedObject.isExpired()) {
cacheHashMap.remove(identifier);
missCount++;
} else {
cachedObject.incNumAccess();
cachedObject.setLastAccessTime(new Date());
hitCount++;
obj = cachedObject.getObject();
}
return obj;
}
public synchronized void invalidate(String identifier) {
cacheHashMap.remove(identifier);
}
public long getHitCount() {
return hitCount;
}
public long getMissCount() {
return missCount;
}
public long getCurrentCacheSize() {
return cacheHashMap.size();
}
public synchronized void putCache(Object object, String id,
int minutesToLive) {
CachedObject cachedObject = new CachedObject(object, id, minutesToLive);
if (cacheHashMap.size() == CACHE_CAPACITY) {
sweep();
}
cacheHashMap.put(id, cachedObject);
}
/**
*cacheHashMap容器的整理
*先将超时的cachedObject清除,
*当cachedObject数量大于TRESHOLD时,将访问频率小(次数小)的cachedObject清除
*/
public synchronized void sweep() {
TreeMap costTreeMap = new TreeMap(new CostComparator());
for (Iterator i = cacheHashMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
CachedObject cachedObject = (CachedObject) entry.getValue();
if (cachedObject.isExpired()) {
cacheHashMap.remove(entry.getKey());
} else {
double cost = 0.0;
switch (purgeAlgorithm) {
case 0:
cost = cachedObject.getLFUCost();
break;
case 1:
cost = cachedObject.getLRUCost();
break;
default:
cost = cachedObject.getMixCost();
}
costTreeMap.put(new Double(cost), entry.getKey());
}
}
// delete to treshold
for (int i = cacheHashMap.size(); i > TRESHOLD; i--) {
Object kk = costTreeMap.firstKey();
Object k = costTreeMap.get(kk);
cacheHashMap.remove(k);
costTreeMap.remove(kk);
}
}
public void clearCache() {
hitCount = 0;
missCount = 0;
cacheHashMap.clear();
}
/**
*将字符数组生成形如:"keys1/keys2/keys3"的字符串
*/
public static String createKey(String[] keys) {
StringBuffer newKey = new StringBuffer("");
for (int i = 0; i < keys.length; i++)
newKey.append(keys[i]).append("/");
return newKey.toString();
}
}
//==============================
DAOCacheManager类
持有一个静态的CacheManager类对象,提供对其的操作方法
业务方法都要通过他来使用cacheManager
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : DAOCacheManager.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.dao;
import java.text.MessageFormat;
import net.cn37signals.company.util.CacheManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class DAOCacheManager {
private static Log log = LogFactory.getFactory().getInstance("DAOCacheManager");
//cacheManager是静态的,供多个线程公用
private static CacheManager cacheManager = new CacheManager(CacheManager.MIX);
/**
*从cache中获取对象
*/
public static Object getCache(String identifier) {
if (log.isInfoEnabled()) {
Object[] o = {new Long(cacheManager.getHitCount()), new Long(cacheManager.getMissCount())};
log.info(MessageFormat.format(" [DAOCacheManager] getCache: {0} hits, {1} misses", o));
}
return cacheManager.getCache(identifier);
}
/**
*将对象放入cache中
*/
public static void putCache(Object object, String id, int minutesToLive) {
if (log.isInfoEnabled()) {
log.info(" [DAOCacheManager] putCache");
}
cacheManager.putCache(object, id, minutesToLive);
}
public static void invalidate(String id) {
cacheManager.invalidate(id);
}
}
//=====================
CachedObject类
对要放入cache的对象进行包装
//---------------------------------------------------------
// Application: Company Applcation
// Author : Cao guangxin
// File : CachedObject.java
//
// Copyright 2006 RelationInfo Software
// Writed at Wed Apr 12 08:58:55 CST 2006
// writed by Eclipse SDK
// Visit http://www.37signals.cn
//---------------------------------------------------------
package net.cn37signals.company.util;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class CachedObject {
public Object object = null;
private Date dateofExpiration = null;
private String identifier = null;
private Date lastAccessTime = new Date();
private long numAccess = 1;
private int size;
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public CachedObject(Object obj, String id, int minutesToLive) {
this.object = obj;
this.identifier = id;
size = objectSize(obj);
lastAccessTime = new Date();
// minutesToLive of 0 means it lives on indefinitely.
if (minutesToLive != 0) {
Calendar cal = Calendar.getInstance();
cal.setTime(lastAccessTime);
cal.add(cal.MINUTE, minutesToLive);
dateofExpiration = cal.getTime();
}
}
public void setLastAccessTime(Date lastAccessTime) {
this.lastAccessTime = lastAccessTime;
}
public boolean isExpired() {
// Remember if the minutes to live is zero then it lives forever!
if (dateofExpiration != null && dateofExpiration.before(new Date())) {
return true;
}
return false;
}
public String getIdentifier() {
return identifier;
}
public Object getObject() {
return object;
}
public Date getDateofExpiration() {
return (this.dateofExpiration);
}
public Date getLastAccessTime() {
return (this.lastAccessTime);
}
public long getNumAccess() {
return (this.numAccess);
}
public long getSize() {
return (this.size);
}
public double getMixCost() {
long milis = new Date().getTime() - lastAccessTime.getTime();
if(milis == 0) {
milis = 1;
}
return (double)numAccess / (double)milis / (double)size;
}
public double getLRUCost() {
long milis = new Date().getTime() - lastAccessTime.getTime();
if(milis == 0) {
milis = 1;
}
return 1.0/(double)milis;
}
public double getLFUCost() {
return (double) numAccess;
}
public void incNumAccess() {
numAccess++;
}
public boolean equals(Object o2) {
try {
String key2 = ((CachedObject) o2).getIdentifier();
return identifier.equals(key2);
} catch (Exception e) {
return false;
}
}
private static int objectSize(Object o) {
try {
int size = ((List) o).size();
return size + 1;
} catch (Exception e) {
return 1;
}
}
}
//==============================
使用方法
public List list(int offset, int limit) throws SQLException {
String[] objKeys = {"Users", "list", String.valueOf(offset), String.valueOf(limit)};
String objKey = CacheManager.createKey(objKeys);
ArrayList list = (ArrayList) DAOCacheManager.getCache(objKey);
//如果cache的hashmap中有,直接取出,没有则从数据库中查询,并放入hashmap中
if (list != null)
return list;
//--
//从数据库中查询(略)
//--
//将查询结果放入cache
DAOCacheManager.putCache(list, objKey, 1);
return list;
}
相关推荐
为了减少高速缓存访问功耗, 提出了一种针对循环的基于历史访问路径的指令高速缓存访问预测方法。该方法以循环作为高速缓存访问路预测行为开启的先决条件, 通过指令高速缓存的历史访问路径训练预测器。当循环体再次...
3. 缓存方法:详细讲解了在Android项目中实现图像缓存的几种常用方法,包括内存缓存、磁盘缓存和第三方库缓存。这些缓存方法可以有效减少网络请求次数,降低服务器压力,提高图像加载速度。 4. 实践案例分析:通过...
基于强化学习的任务缓存和计算卸载效益最大化算法是一种用于优化任务调度和计算资源利用的算法。该算法结合了强化学习方法和任务缓存、计算卸载技术,旨在实现任务执行的高效性和资源利用的最大化。
LRU缓存算法是一种常用的缓存淘汰策略,它根据数据项最近被使用的时间来决定哪些数据项应该从缓存中移除,以确保缓存中始终存放着最近最可能被使用的数据项。这个压缩文件可能包括LRU缓存的实现代码、测试样例、使用...
最近项目中自己研发的一款适用于分布式服务器的非session实现的验证码框架。文章链接:http://blog.csdn.net/chaijunkun/article/details/8996794,共同学习。
ibatis 缓存配置策略,学习篇 • iBatis对查询结果集进行本地缓存。 • Cache的key由haskcode、checksum、查询参数、sqlmap Id、sql语句、调用方法名等构成。由此可以看出,不同的参数会有不同的Key。注意,他不是以...
随着微服务的应用不断增多,各服务之间的数据需 要多方共享成为急需解决的技术问题,应用层缓存技术 ...本文提出一种利用 Redis 进行微 服务之间数据共享的缓存方案,以解决各服务之间的数 据冗余、数据孤岛问题
QoE驱动的以内容为中心的缓存,以及启用边缘的物联网中的深度强化学习
在数据解析方面,程序利用XPath解析器,这是一种强大的XML文档查询工具,它允许用户通过简洁的路径表达式来定位和提取所需的信息。这种高效的数据处理方式,确保了信息抽取的准确性和灵活性。 需要特别强调的是,本...
最近项目中自己研发的一款适用于分布式服务器的非session实现的验证码框架。文章链接:http://blog.csdn.net/chaijunkun/article/details/8996794,共同学习。
针对信息中心网络(ICN)环境下缓存内容放置优化问题,提出一种边缘优先逐级反馈的缓存协作策略(ECCS)。该策略通过将缓存决策提前至请求转发阶段,将下游节点的缓存决策信息及内容统计信息逐级反馈给上游节点,以...
缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝。 Web应用缓存技术大体上可以分为两类:服务端缓存和客户端缓存。两种目标都是...
针对深度强化学习算法中经验缓存机制构建问题,提出一种基于TD误差的重抽样优选缓存机制;针对该机制存在的训练集坍塌现象,提出基于排行的分层抽样算法进行改进,并结合该机制对已有的几种典型基于DQN的深度强化学习...
System.Transactions是.NET Framework 2.0下出现的一个事务控制的命名空间,它是处理替代COM+来处理分布式事务的一种新的途径。 2.使用泛型的强类型代替了IList。 3.使用了ASP.NET2.0下的角色及成员管理。 4.对于...
为了克服FAR算法在位置预测方面的不足,定义了一种语义缓存模型,与传统的语义缓存模型相比增加了对移动单元的坐标和语义片段的时间描述,有助于预测未来移动单元可能的位置。提出了一个改进的RBF-FAR算法作为替换...
一直很想学习缓存这一块儿的东西,毕竟前端性能优化缓存在其中占了很大一部分作用。缓存分为两种:强制缓存和协商缓存。看过很多文章讲它们之间的区别,但是没有实战过只知道其意义却不知道怎样去设置,没有实战过也...
发明名称:一种基于FPGA的卷积神经网络硬件加速架构 摘要 本发明公开一种基于FPGA的卷积神经网络硬件加速架构,包括:通用AXI4总线接口;用于缓存输入特征图,输出特征图和权重的缓存区;用于引导运算结果缓存的...
QSV是一种缓存文件,只能使用其专用播放器进行播放,如果想转换到其他格式,就必须要用到这个视频转换器。除了转换单个文件外,还可以添加批量文件转换。使用非常简单,添加文件开始转换就可以了。V2.2更新说明: 1...
一种是装饰样式,另一种是将函数注册到隐藏函数,并添加目标函数作为参数。装饰我们只将可恢复对象添加到目标函数中。 @resumable()def generate(): sleep(10) return {"foobar": "bar"}如果要缓存对象的实例方法的...
适用于Redis Enterprise的Azure缓存一种采用Redis Enterprise的Azure缓存的框架,该框架试图与保持一致入门克隆存储库git@github.com:redisgeek/acre-adoption.git将CD放入存储库cd acre-adoption使用docker服务内容...