本地快取
阿新 • • 發佈:2020-07-21
1.單機本地快取
本地快取的一種簡單實現
首先定義一個快取實體,包含三個屬性放入快取的時間戳,值以及過期時間;其次需要個執行緒去監控快取實體是否過期。
/** * *本地快取儲存的實體 */ 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(longgmtModify) { 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; } }
/** * 簡易本地快取的實現類 */ 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<String, CacheEntity> cache = new ConcurrentHashMap<String, CacheEntity>(DEFAULT_CAPACITY); /** * 將key-value 儲存到本地快取並制定該快取的過期時間 * @param key * @param value * @param expireTime 過期時間,如果是-1 則表示永不過期 * @return */ public boolean putValue(String key, Object value, int expireTime) { return putCloneValue(key, value, expireTime); } /** * 將值通過序列化clone 處理後儲存到快取中,可以解決值引用的問題 * @param key * @param value * @param expireTime * @return */ 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; } /** * * 序列化 克隆處理 * @param object * @return */ private <T extends Serializable> 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; } /** *從本地快取中獲取key對應的值,如果該值不存則則返回null * @param key * @return */ 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(); } } } /** * 過期快取的具體處理方法 * @throws Exception */ 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); } } } }