最近項目要引入緩存機制,可是不想引入分佈式的緩存框架,因此本身就寫了一個輕量級的緩存實現,有兩個版本,一個是經過timer實現其超時過時處理,另一個是經過list輪詢。
首先要了解下java1.6中的ConcurrentMap ,他是一個線程安全的Map實現,特別說明的是在沒有特別需求的狀況下能夠用ConcurrentHashMap。我是想學習一下讀寫鎖的應用,就本身實現了一個SimpleConcurrentHashMap.
html
package com.cttc.cache.entity; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class SimpleConcurrentMap<K, V> implements Map<K, V> { final ReadWriteLock lock = new ReentrantReadWriteLock(); final Lock r = lock.readLock(); final Lock w = lock.writeLock(); final Map<K, V> map; public SimpleConcurrentMap(Map<K, V> map) { this.map = map; if (map == null) throw new NullPointerException(); } public void clear() { w.lock(); try { map.clear(); } finally { w.unlock(); } } public boolean containsKey(Object key) { r.lock(); try { return map.containsKey(key); } finally { r.unlock(); } } public boolean containsValue(Object value) { r.lock(); try { return map.containsValue(value); } finally { r.unlock(); } } public Set<java.util.Map.Entry<K, V>> entrySet() { throw new UnsupportedOperationException(); } public V get(Object key) { r.lock(); try { return map.get(key); } finally { r.unlock(); } } public boolean isEmpty() { r.lock(); try { return map.isEmpty(); } finally { r.unlock(); } } public Set<K> keySet() { r.lock(); try { return new HashSet<K>(map.keySet()); } finally { r.unlock(); } } public V put(K key, V value) { w.lock(); try { return map.put(key, value); } finally { w.unlock(); } } public void putAll(Map<? extends K, ? extends V> m) { w.lock(); try { map.putAll(m); } finally { w.unlock(); } } public V remove(Object key) { w.lock(); try { return map.remove(key); } finally { w.unlock(); } } public int size() { r.lock(); try { return map.size(); } finally { r.unlock(); } } public Collection<V> values() { r.lock(); try { return new ArrayList<V>(map.values()); } finally { r.unlock(); } } }
緩存對象CacheEntity.java爲:
java
package com.cttc.cache.entity; import java.io.Serializable; public class CacheEntity implements Serializable{ private static final long serialVersionUID = -3971709196436977492L; private final int DEFUALT_VALIDITY_TIME = 20;//默認過時時間 20秒 private String cacheKey; private Object cacheContext; private int validityTime;//有效期時長,單位:秒 private long timeoutStamp;//過時時間戳 private CacheEntity(){ this.timeoutStamp = System.currentTimeMillis() + DEFUALT_VALIDITY_TIME * 1000; this.validityTime = DEFUALT_VALIDITY_TIME; } public CacheEntity(String cacheKey, Object cacheContext){ this(); this.cacheKey = cacheKey; this.cacheContext = cacheContext; } public CacheEntity(String cacheKey, Object cacheContext, long timeoutStamp){ this(cacheKey, cacheContext); this.timeoutStamp = timeoutStamp; } public CacheEntity(String cacheKey, Object cacheContext, int validityTime){ this(cacheKey, cacheContext); this.validityTime = validityTime; this.timeoutStamp = System.currentTimeMillis() + validityTime * 1000; } public String getCacheKey() { return cacheKey; } public void setCacheKey(String cacheKey) { this.cacheKey = cacheKey; } public Object getCacheContext() { return cacheContext; } public void setCacheContext(Object cacheContext) { this.cacheContext = cacheContext; } public long getTimeoutStamp() { return timeoutStamp; } public void setTimeoutStamp(long timeoutStamp) { this.timeoutStamp = timeoutStamp; } public int getValidityTime() { return validityTime; } public void setValidityTime(int validityTime) { this.validityTime = validityTime; } }
List緩存處理對象:
緩存
package com.cttc.cache.handler; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.cttc.cache.entity.CacheEntity; import com.cttc.cache.entity.SimpleConcurrentMap; /** * @projName:WZServer * @className:CacheHandler * @description:緩存操做類,對緩存進行管理,採用處理隊列,定時循環清理的方式 * @creater:Administrator * @creatTime:2013年7月22日 上午9:18:54 * @alter:Administrator * @alterTime:2013年7月22日 上午9:18:54 * @remark: * @version */ public class CacheListHandler { private static final long SECOND_TIME = 1000; private static final SimpleConcurrentMap<String, CacheEntity> map; private static final List<CacheEntity> tempList; static{ tempList = new ArrayList<CacheEntity>(); map = new SimpleConcurrentMap<String, CacheEntity>(new HashMap<String, CacheEntity>(1<<18)); new Thread(new TimeoutTimerThread()).start(); } /** * 增長緩存對象 * @param key * @param ce */ public static void addCache(String key, CacheEntity ce){ addCache(key, ce, ce.getValidityTime()); } /** * 增長緩存對象 * @param key * @param ce * @param validityTime 有效時間 */ public static synchronized void addCache(String key, CacheEntity ce, int validityTime){ ce.setTimeoutStamp(System.currentTimeMillis() + validityTime * SECOND_TIME); map.put(key, ce); //添加到過時處理隊列 tempList.add(ce); } /** * 獲取緩存對象 * @param key * @return */ public static synchronized CacheEntity getCache(String key){ return map.get(key); } /** * 檢查是否含有制定key的緩衝 * @param key * @return */ public static synchronized boolean isConcurrent(String key){ return map.containsKey(key); } /** * 刪除緩存 * @param key */ public static synchronized void removeCache(String key){ map.remove(key); } /** * 獲取緩存大小 * @param key */ public static int getCacheSize(){ return map.size(); } /** * 清除所有緩存 */ public static synchronized void clearCache(){ tempList.clear(); map.clear(); System.out.println("clear cache"); } static class TimeoutTimerThread implements Runnable { public void run(){ while(true){ try { checkTime(); } catch (Exception e) { e.printStackTrace(); } } } /** * 過時緩存的具體處理方法 * @throws Exception */ private void checkTime() throws Exception{ //"開始處理過時 "; CacheEntity tce = null; long timoutTime = 1000L; //" 過時隊列大小 : "+tempList.size()); if(1 > tempList.size()){ System.out.println("過時隊列空,開始輪詢"); timoutTime = 1000L; Thread.sleep(timoutTime); return; } tce = tempList.get(0); timoutTime = tce.getTimeoutStamp() - System.currentTimeMillis(); //" 過時時間 : "+timoutTime); if(0 < timoutTime){ //設定過時時間 Thread.sleep(timoutTime); return; } System.out.print(" 清除過時緩存 : "+tce.getCacheKey()); //清除過時緩存和刪除對應的緩存隊列 tempList.remove(tce); removeCache(tce.getCacheKey()); } } }
Timer方式
安全
package com.cttc.cache.handler; import java.util.HashMap; import java.util.Timer; import java.util.TimerTask; import com.cttc.cache.entity.CacheEntity; import com.cttc.cache.entity.SimpleConcurrentMap; /** * @projName:WZServer * @className:CacheHandler * @description:緩存操做類,對緩存進行管理,清除方式採用Timer定時的方式 * @creater:Administrator * @creatTime:2013年7月22日 上午9:18:54 * @alter:Administrator * @alterTime:2013年7月22日 上午9:18:54 * @remark: * @version */ public class CacheTimerHandler { private static final long SECOND_TIME = 1000;//默認過時時間 20秒 private static final int DEFUALT_VALIDITY_TIME = 20;//默認過時時間 20秒 private static final Timer timer ; private static final SimpleConcurrentMap<String, CacheEntity> map; static{ timer = new Timer(); map = new SimpleConcurrentMap<String, CacheEntity>(new HashMap<String, CacheEntity>(1<<18)); } /** * 增長緩存對象 * @param key * @param ce */ public static void addCache(String key, CacheEntity ce){ addCache(key, ce, DEFUALT_VALIDITY_TIME); } /** * 增長緩存對象 * @param key * @param ce * @param validityTime 有效時間 */ public static synchronized void addCache(String key, CacheEntity ce, int validityTime){ map.put(key, ce); //添加過時定時 timer.schedule(new TimeoutTimerTask(key), validityTime * SECOND_TIME); } /** * 獲取緩存對象 * @param key * @return */ public static synchronized CacheEntity getCache(String key){ return map.get(key); } /** * 檢查是否含有制定key的緩衝 * @param key * @return */ public static synchronized boolean isConcurrent(String key){ return map.containsKey(key); } /** * 刪除緩存 * @param key */ public static synchronized void removeCache(String key){ map.remove(key); } /** * 獲取緩存大小 * @param key */ public static int getCacheSize(){ return map.size(); } /** * 清除所有緩存 */ public static synchronized void clearCache(){ if(null != timer){ timer.cancel(); } map.clear(); System.out.println("clear cache"); } /** * @projName:WZServer * @className:TimeoutTimerTask * @description:清除超時緩存定時服務類 * @creater:Administrator * @creatTime:2013年7月22日 上午9:34:39 * @alter:Administrator * @alterTime:2013年7月22日 上午9:34:39 * @remark: * @version */ static class TimeoutTimerTask extends TimerTask{ private String ceKey ; public TimeoutTimerTask(String key){ this.ceKey = key; } @Override public void run() { CacheTimerHandler.removeCache(ceKey); System.out.println("remove : "+ceKey); } } }
timer方式有點是適用性更強,由於每一個緩存的過時時間均可以獨立配置的;ist只能適用於緩存時間都同樣的線性過時。從性能開銷方面,由於timer是與緩存對象數量成正比的,在緩存量很大的時候,在緩存時間內系統開銷也隨之提升;而list方式只要一個線程管理過時清理就能夠了。框架
這裏要感謝飯飯泛,從其微博學習到不少http://www.blogjava.net/xylz/archive/2010/07/14/326080.html
分佈式