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;
}
分享到:
相关推荐
不过,需要注意的是,如果查询涉及到动态条件或随机排序,可能需要使用`forgetCache`方法手动清除缓存,以避免返回过期数据。 在更新、创建或删除记录后,通常需要清除相关的缓存,以保持数据的一致性。Laravel提供...
在Java编程中,缓存(Cache)是一种常用的数据结构,用于临时存储经常访问的数据,以提高数据访问效率。本文将深入探讨如何使用Java实现一个基于LinkedHashMap的LRU(Least Recently Used,最近最少使用)缓存策略。...
在使用 `Rediscache` 插件时,一定要参考插件的官方文档,了解其完整功能和最佳实践,以便更好地利用Redis服务提升你的应用程序性能。同时,保持对Redis最新版本的关注,以获得更好的性能和新特性。
这可以通过在分支取指时保存前端寄存器状态并对比分支旧的指令结果来实现。 此外,现代处理器的流水线设计包括保留站和重排序缓冲区两个“驼峰”,分别对应调度窗口和指令窗口。乱序执行通过寄存器重命名、缓冲和...
在“搜索引擎的设计与实现”这个主题中,我们将探讨搜索引擎的基本原理、主要组成部分以及实现过程,这是一份非常适合计算机科学专业学生作为毕业设计练习的课题。 搜索引擎的核心概念包括以下几个部分: 1. **...
插入排序是一种简单的排序算法,它通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。虽然效率较低,但对于小规模数据集仍然有效。 ### 五十二、Vuex数据存储位置 Vuex是Vue.js...
本文将详细解析"Android优化增强的缓存机制",重点介绍一种基于LRU(Least Recently Used)策略的缓存实现,以及相关的辅助工具类,以帮助开发者更有效地管理资源。 LRU缓存是一种常用的内存管理策略,其基本原理是...
3. 起泡排序改为奇偶转置排序,消除了循环步间的数据依赖的原因是改为元素两两分组比较。 4. 求解同一个问题的 4 个并行算法的等效率函数分析结果,其中 Θ(plogp) 的可扩展性最优。 5. 为防止编译器不支持 OpenMP,...
在Java的持久化框架Hibernate中,二级缓存和分页功能是两个重要的...在具体实现时,还需要根据业务需求和系统环境选择合适的缓存策略和分页方案。文件`s.7z`和`h.7z`可能包含示例代码或配置文件,供开发者参考学习。
拓扑排序是对有向无环图(DAG)的顶点的一种线性排序方式,使得对于任意一对顶点u、v,如果图中存在一条从u到v的路径,则在排序结果中,u出现在v之前。拓扑排序可以用于任务调度等问题。 **实现方法**: 1. **入度...
拓扑排序是对有向无环图(DAG)的顶点的一种线性排序,其中对于任何边(u, v),u总是在v之前。通常使用BFS或DFS实现。 6. **稳定排序与不稳定排序**: 稳定排序算法保持相等元素的相对顺序,而不稳定排序可能会...
缓存不命中主要包括三种类型: - **强制性不命中**(Compulsory Misses):当数据首次被访问时,因为该数据还未被加载到缓存中而导致的不命中。即使拥有无限大的缓存也无法避免这种情况。 - **容量不命中**...
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...
在移动应用开发中,APICloud提供了一种混合开发模式,允许开发者使用JavaScript编写应用程序,并通过API与原生平台进行交互。这种模式极大地提高了开发效率,但也带来了一些性能问题,尤其是在处理大量数据或频繁...
例如,`LOCALE`参数设定服务器返回的数据的语言环境,`SORT_ORDER_LOCALE`定义排序的语言环境,`SORT_TYPE`决定排序方式,默认为二进制排序,非二进制排序可能对性能有不同影响。`CASE_SENSITIVE_CHARACTER_...
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 13、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 14、...
3. **奇偶转置排序**:这种排序方法通过改变比较的方式,消除了相邻元素之间的数据依赖,使得并行化更容易。 4. **并行算法的可扩展性**:可扩展性衡量并行算法在增加处理器数量时性能提升的程度。题目中提到的`Θ...
6. **复杂查询支持**:Elocache不仅支持简单的查询缓存,还能够处理包括联接、分组、排序、限制等在内的复杂查询。 在"Lumem-Elocache-master"这个压缩包中,包含了Elocache库的源代码,你可以查阅这些代码来了解其...
CACHE策略优化了内存管理,中文词汇学习技术则改进了对中文词汇的理解。最后,用户行为分析技术使搜索引擎能够适应用户需求的变化。 论文中还简要介绍了系统的实际实现和性能测试,并对“天网”系统的未来发展方向...
16. 现代 CPU:现代 CPU 中都具有指令乱序执行功能,其目的包括消除指令依赖,更充分利用多流水线、提高 cache 效率等。 17. 并行代价:记并行时间为 T,串行时间为 T',处理器数量为 p,并行代价的定义是 pT。 18...