java java local cache本地緩存的兩種實現,一個基於list輪詢一個基於timer定時

       最近項目要引入緩存機制,可是不想引入分佈式的緩存框架,因此本身就寫了一個輕量級的緩存實現,有兩個版本,一個是經過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
























分佈式

相關文章
相關標籤/搜索