`
johnnyhg
  • 浏览: 343503 次
  • 来自: NA
社区版块
存档分类
最新评论

简单实现三种清除cache时的排序策略

阅读更多
CacheManager类
使用一个HashMap来缓存从数据库中查询出的Object,并提供获取,存放,清除的方法
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;
}
分享到:
评论

相关推荐

    java 面试题 总结

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...

    asp.net知识库

    自定义通用System.Web.UI.IHierarchicalDataSource简单实现 在 ASP.NET 2.0 中创建 Web 应用程序主题 ASP.NET 2.0 中的数据访问 ASP.NET 2.0:弃用 DataGrid 吧,有新的网格控件了! 将 ASP.NET 2.0 应用程序服务...

    超级有影响力霸气的Java面试题大全文档

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 13、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 14、...

    一个大规模、高性能的搜索引擎系统—北京大学硕士研究生学位论文

    分布式并行搜集技术、启发式搜集策略、镜像消除技术、中英文特征项提取技术、高效索引技术、词典更新技术、超链分析技术、快速检索技术、相关度评价策略、Hash排序算法、Cache策略、中文词汇学习技术和用户行为分析...

    NHibernate参考文档 2.0.0 chm

    8.1. 三种策略 8.1.1. 每个类分层结构一张表(Table per class hierarchy) 8.1.2. 每个子类一张表(Table per subclass) 8.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 8.1.4. 混合使用...

    NHibernate中文帮组文档(2008.11月更新)

    8.1. 三种策略 8.1.1. 每个类分层结构一张表(Table per class hierarchy) 8.1.2. 每个子类一张表(Table per subclass) 8.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 8.1.4. 混合使用...

    C#微软培训资料

    2.2 公用语言运行时环境与公用语言规范.13 2.3 开 发 工 具 .17 2.4 小 结 .19 第三章 编写第一个应用程序 .20 3.1 Welcome 程序 .20 3.2 代 码 分 析 .20 3.3 运 行 程 序 .23 .4 添 加 注 释 .25 ...

    spring security 参考手册中文版

    10.1.1成功认证时清除证书 91 10.1.2 DaoAuthenticationProvider 91 10.2 UserDetailsService实现 92 10.2.1内存认证 92 10.2.2 JdbcDaoImpl 93 权威组织 94 10.3密码编码 94 10.3.1什么是散列? 95 10.3.2添加盐到...

    会计理论考试题

    A、计算机病毒通常是一段可运行的程序 B、反病毒软件可清除所有病毒 C、加装防病毒卡的微机不会感染病毒 D、病毒不会通过网络传染 14.在Windows98中,如果删除了软盘上的文件,则该文件在Windows98中___A____。 A、...

    SQLServer2008查询性能优化 2/2

    当服务器的运行越来越慢时,这个工作就变得更加困难。来自用户的愤怒的电话以及站在你办公桌周围的管理人员都使你很不快活。在开发代码的同时,如果你花费时间和精力来开发一个性能故障排错的方法。那么你就能避免...

    SQLServer2008查询性能优化 1/2

    当服务器的运行越来越慢时,这个工作就变得更加困难。来自用户的愤怒的电话以及站在你办公桌周围的管理人员都使你很不快活。在开发代码的同时,如果你花费时间和精力来开发一个性能故障排错的方法。那么你就能避免...

Global site tag (gtag.js) - Google Analytics