在Javaweb 項目中對頻繁讀取且相對穩定的資料一般都是用了緩存,這樣可以極大地減少資料庫的壓力且提高的響應的速度。 一般都是,通過key 從緩存中讀取value 如果value 為空則讀取DB,将DB讀取的資料再放入緩存這樣的一個過程。
一個簡易的本地緩存實作。
首先資料一般都是有時效性的,不是放入緩存就一直存在,如果超過一定時間沒有被使用則應當被清空,使其系統中不會使用到過期資料。
下面是對本地緩存的一種簡單實作
首先定義一個緩存實體,包含三個屬性 放入緩存的時間戳,值以及過期時間;其次需要個線程去監控緩存實體是否過期。
public class CacheEntity implements Serializable {
private static final long serialVersionUID = 7172649826282703560L;
private Object value;
private long gmtModify;
private int expire;
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public long getGmtModify() {
return gmtModify;
}
public void setGmtModify(long gmtModify) {
this.gmtModify = gmtModify;
}
public int getExpire() {
return expire;
}
public void setExpire(int expire) {
this.expire = expire;
}
public CacheEntity(Object value, long gmtModify, int expire) {
super();
this.value = value;
this.gmtModify = gmtModify;
this.expire = expire;
}
}
Java代碼
public class LocalCache {
//預設的緩存容量
private static int DEFAULT_CAPACITY = 512;
//最大容量
private static int MAX_CAPACITY = 100000;
//重新整理緩存的頻率
private static int MONITOR_DURATION = 2;
// 啟動監控線程
static {
new Thread(new TimeoutTimerThread()).start();
}
//使用預設容量建立一個Map
private static ConcurrentHashMap cache = new ConcurrentHashMap(
DEFAULT_CAPACITY);
public boolean putValue(String key, Object value, int expireTime) {
return putCloneValue(key, value, expireTime);
}
private boolean putCloneValue(String key, Object value, int expireTime) {
try {
if (cache.size() >= MAX_CAPACITY) {
return false;
}
// 序列化指派
CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime));
cache.put(key, entityClone);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private T clone(T object) {
T cloneObject = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
cloneObject = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObject;
}
public Object getValue(String key) {
return cache.get(key).getValue();
}
public void clear() {
cache.clear();
}
static class TimeoutTimerThread implements Runnable {
public void run() {
while (true) {
try {
System.out.println("Cache monitor");
TimeUnit.SECONDS.sleep(MONITOR_DURATION);
checkTime();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void checkTime() throws Exception {
//"開始處理過期 ";
for (String key : cache.keySet()) {
CacheEntity tce = cache.get(key);
long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()
- tce.getGmtModify());
//" 過期時間 : "+timoutTime);
if (tce.getExpire() > timoutTime) {
continue;
}
System.out.println(" 清除過期緩存 : " + key);
//清除過期緩存和删除對應的緩存隊列
cache.remove(key);
}
}
}
}