1. 程式人生 > 實用技巧 >本地快取

本地快取

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(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;   } }
/**
* 簡易本地快取的實現類
*/
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);
            }
        }
    }

}

轉載:https://www.iteye.com/blog/wujiu-2179087