下面这个基于map的简单内存cache是在去年一个项目中编写的,主要参考了ibatis的cacheModel源码,不过最终没有采用。缓存的策略选择和应用的负载情况息息相关,当时根据应用系统jvm的full gc频率和用户访问频次较低的特点,采用了SoftReference+LRU的缓存策略。
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import com.alibaba.common.logging.Logger;
import com.alibaba.common.logging.LoggerFactory;
import com.ibatis.sqlmap.engine.cache.memory.MemoryCacheLevel;
public class CubeCacheImpl {
private final static Logger LOG = LoggerFactory.getLogger("DW-CACHE");
private MemoryCacheLevel referenceType = MemoryCacheLevel.SOFT;
//存放对象的map
private final Map<Object, Object> cache = new ConcurrentHashMap<Object, Object>();
//保存的对象个数
private int cacheSize = 100;
//存放key的list
private final List<Object> keyList = new CopyOnWriteArrayList<Object>();
//最近一次清空时间
private Date recentTime = null;
public MemoryCacheLevel getReferenceType() {
return referenceType;
}
public void setReferenceType(MemoryCacheLevel referenceType) {
this.referenceType = referenceType;
}
/**
* 向cache中放入对象
*
* @param cacheModel The cacheModel
* @param key The key of the object to be cached
* @param value The object to be cached
*/
public void putObject(Object key, Object value) {
Object reference = null;
if (referenceType.equals(MemoryCacheLevel.WEAK)) {
reference = new WeakReference<Object>(value);
} else if (referenceType.equals(MemoryCacheLevel.SOFT)) {
reference = new SoftReference<Object>(value);
} else if (referenceType.equals(MemoryCacheLevel.STRONG)) {
reference = new StrongReference(value);
}
cache.put(key, reference);
keyList.add(key);
if (keyList.size() > cacheSize) {
try {
Object oldestKey = keyList.remove(0);
cache.remove(oldestKey);
} catch (IndexOutOfBoundsException e) {
//此处应该执行不到
LOG.error(e);
}
}
}
/**
* 从cache中获取对象
*
* @param cacheModel The cache model
* @param key The key of the object to be returned
* @return The cached object (or null)
*/
public Object getObject(Object key) {
Object value = null;
Object ref = cache.get(key);
keyList.remove(key);
if (ref != null) {
keyList.add(key);
if (ref instanceof StrongReference) {
value = ((StrongReference) ref).get();
} else if (ref instanceof SoftReference<?>) {
value = ((SoftReference<Object>) ref).get();
} else if (ref instanceof WeakReference<?>) {
value = ((WeakReference<Object>) ref).get();
}
}
return value;
}
/**
* 检查日期,是否有数据更新要刷新缓存
*
* @return
*/
private boolean checkDate() {
Date refreshTime = getDataRefreshTime();
if (recentTime == null || recentTime.before(refreshTime)) {
recentTime = refreshTime;
return true;
}
return false;
}
/**
* 获取后台数据更新时间,用于判断是否需要cache刷新
*
* @return
*/
private Date getDataRefreshTime() {
//TODO 测试代码,这里的时间包含两部分,一是后台导数时间,二是ETL同步数据时间,此处的策略需要再细化
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -2);
Date date = calendar.getTime();
return date;
}
public Object removeObject(Object key) {
Object value = null;
Object ref = cache.remove(key);
keyList.remove(key);
if (ref != null) {
if (ref instanceof StrongReference) {
value = ((StrongReference) ref).get();
} else if (ref instanceof SoftReference<?>) {
value = ((SoftReference<Object>) ref).get();
} else if (ref instanceof WeakReference<?>) {
value = ((WeakReference<Object>) ref).get();
}
}
return value;
}
/**
* 清空cache
*
*/
public void flush() {
cache.clear();
keyList.clear();
}
/**
* Class to implement a strong (permanent) reference.
*/
private static class StrongReference {
private final Object object;
/**
* StrongReference constructor for an object
* @param object - the Object to store
*/
public StrongReference(Object object) {
this.object = object;
}
/**
* Getter to get the object stored in the StrongReference
* @return - the stored Object
*/
public Object get() {
return object;
}
}
}