java local cache本地缓存的两种实现,一个基于list轮询一个基于timer定时



java local cache本地缓存的两种实现,一个基于list轮询一个基于timer定时。 最近项目要引入缓存机制,但是不想引入分布式的缓存框架,所以自己就写了一个轻量级的缓存实现,有两个版本,一个是通过timer实现其超时过期处理,另外一个是通过list轮询。        首先要了解下java1.6中的ConcurrentMap ,他是一个线程安全的Map实现,特别说明的是在没有特别需求的情况下可以用ConcurrentHashMap。我是想学习一下读写锁的应用,就自己实现了一个SimpleConcurrentHashMap.

  1. package com.cttc.cache.entity;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.HashSet;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.concurrent.locks.Lock;
  8. import java.util.concurrent.locks.ReadWriteLock;
  9. import java.util.concurrent.locks.ReentrantReadWriteLock;
  10. public class SimpleConcurrentMap<K, V> implements Map<K, V> {
  11.     final ReadWriteLock lock = new ReentrantReadWriteLock();
  12.     final Lock r = lock.readLock();
  13.     final Lock w = lock.writeLock();
  14.     final Map<K, V> map;
  15.     public SimpleConcurrentMap(Map<K, V> map) {
  16.         this.map = map;
  17.         if (map == null) throw new NullPointerException();
  18.     }
  19.     public void clear() {
  20.         w.lock();
  21.         try {
  22.             map.clear();
  23.         } finally {
  24.             w.unlock();
  25.         }
  26.     }
  27.     public boolean containsKey(Object key) {
  28.         r.lock();
  29.         try {
  30.             return map.containsKey(key);
  31.         } finally {
  32.             r.unlock();
  33.         }
  34.     }
  35.     public boolean containsValue(Object value) {
  36.         r.lock();
  37.         try {
  38.             return map.containsValue(value);
  39.         } finally {
  40.             r.unlock();
  41.         }
  42.     }
  43.     public Set<java.util.Map.Entry<K, V>> entrySet() {
  44.         throw new UnsupportedOperationException();
  45.     }
  46.     public V get(Object key) {
  47.         r.lock();
  48.         try {
  49.             return map.get(key);
  50.         } finally {
  51.             r.unlock();
  52.         }
  53.     }
  54.     public boolean isEmpty() {
  55.         r.lock();
  56.         try {
  57.             return map.isEmpty();
  58.         } finally {
  59.             r.unlock();
  60.         }
  61.     }
  62.     public Set<K> keySet() {
  63.         r.lock();
  64.         try {
  65.             return new HashSet<K>(map.keySet());
  66.         } finally {
  67.             r.unlock();
  68.         }
  69.     }
  70.     public V put(K key, V value) {
  71.         w.lock();
  72.         try {
  73.             return map.put(key, value);
  74.         } finally {
  75.             w.unlock();
  76.         }
  77.     }
  78.     public void putAll(Map<? extends K, ? extends V> m) {
  79.         w.lock();
  80.         try {
  81.             map.putAll(m);
  82.         } finally {
  83.             w.unlock();
  84.         }
  85.     }
  86.     public V remove(Object key) {
  87.         w.lock();
  88.         try {
  89.             return map.remove(key);
  90.         } finally {
  91.             w.unlock();
  92.         }
  93.     }
  94.     public int size() {
  95.         r.lock();
  96.         try {
  97.             return map.size();
  98.         } finally {
  99.             r.unlock();
  100.         }
  101.     }
  102.     public Collection<V> values() {
  103.         r.lock();
  104.         try {
  105.             return new ArrayList<V>(map.values());
  106.         } finally {
  107.             r.unlock();
  108.         }
  109.     }
  110. }
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为:

  1. package com.cttc.cache.entity;
  2. import java.io.Serializable;
  3. public class CacheEntity implements Serializable{
  4.     private static final long serialVersionUID = -3971709196436977492L;
  5.     private final int DEFUALT_VALIDITY_TIME = 20;//默认过期时间 20秒
  6.     private String cacheKey;
  7.     private Object cacheContext;
  8.     private int validityTime;//有效期时长,单位:秒
  9.     private long timeoutStamp;//过期时间戳
  10.     private CacheEntity(){
  11.         this.timeoutStamp = System.currentTimeMillis() + DEFUALT_VALIDITY_TIME * 1000;
  12.         this.validityTime = DEFUALT_VALIDITY_TIME;
  13.     }
  14.     public CacheEntity(String cacheKey, Object cacheContext){
  15.         this();
  16.         this.cacheKey = cacheKey;
  17.         this.cacheContext = cacheContext;
  18.     }
  19.     public CacheEntity(String cacheKey, Object cacheContext, long timeoutStamp){
  20.         this(cacheKey, cacheContext);
  21.         this.timeoutStamp = timeoutStamp;
  22.     }
  23.     public CacheEntity(String cacheKey, Object cacheContext, int validityTime){
  24.         this(cacheKey, cacheContext);
  25.         this.validityTime = validityTime;
  26.         this.timeoutStamp = System.currentTimeMillis() + validityTime * 1000;
  27.     }
  28.     public String getCacheKey() {
  29.         return cacheKey;
  30.     }
  31.     public void setCacheKey(String cacheKey) {
  32.         this.cacheKey = cacheKey;
  33.     }
  34.     public Object getCacheContext() {
  35.         return cacheContext;
  36.     }
  37.     public void setCacheContext(Object cacheContext) {
  38.         this.cacheContext = cacheContext;
  39.     }
  40.     public long getTimeoutStamp() {
  41.         return timeoutStamp;
  42.     }
  43.     public void setTimeoutStamp(long timeoutStamp) {
  44.         this.timeoutStamp = timeoutStamp;
  45.     }
  46.     public int getValidityTime() {
  47.         return validityTime;
  48.     }
  49.     public void setValidityTime(int validityTime) {
  50.         this.validityTime = validityTime;
  51.     }
  52. }
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缓存处理对象:

  1. package com.cttc.cache.handler;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import com.cttc.cache.entity.CacheEntity;
  6. import com.cttc.cache.entity.SimpleConcurrentMap;
  7. /**
  8. * @projName:WZServer
  9. * @className:CacheHandler
  10. * @description:缓存操作类,对缓存进行管理,采用处理队列,定时循环清理的方式
  11. * @creater:Administrator
  12. * @creatTime:2013年7月22日 上午9:18:54
  13. * @alter:Administrator
  14. * @alterTime:2013年7月22日 上午9:18:54
  15. * @remark:
  16. * @version
  17. */
  18. public class CacheListHandler {
  19.     private static final long SECOND_TIME = 1000;
  20.     private static final SimpleConcurrentMap<String, CacheEntity> map;
  21.     private static final List<CacheEntity> tempList;
  22.     static{
  23.         tempList = new ArrayList<CacheEntity>();
  24.         map = new SimpleConcurrentMap<String, CacheEntity>(new HashMap<String, CacheEntity>(1<<18));
  25.         new Thread(new TimeoutTimerThread()).start();
  26.     }
  27.     /**
  28.      * 增加缓存对象
  29.      * @param key
  30.      * @param ce
  31.      */
  32.     public static void addCache(String key, CacheEntity ce){
  33.         addCache(key, ce, ce.getValidityTime());
  34.     }
  35.     /**
  36.      * 增加缓存对象
  37.      * @param key
  38.      * @param ce
  39.      * @param validityTime 有效时间
  40.      */
  41.     public static synchronized void addCache(String key, CacheEntity ce, int validityTime){
  42.         ce.setTimeoutStamp(System.currentTimeMillis() + validityTime * SECOND_TIME);
  43.         map.put(key, ce);
  44.         //添加到过期处理队列
  45.         tempList.add(ce);
  46.     }
  47.     /**
  48.      * 获取缓存对象
  49.      * @param key
  50.      * @return
  51.      */
  52.     public static synchronized CacheEntity getCache(String key){
  53.         return map.get(key);
  54.     }
  55.     /**
  56.      * 检查是否含有制定key的缓冲
  57.      * @param key
  58.      * @return
  59.      */
  60.     public static synchronized boolean isConcurrent(String key){
  61.         return map.containsKey(key);
  62.     }
  63.     /**
  64.      * 删除缓存
  65.      * @param key
  66.      */
  67.     public static synchronized void removeCache(String key){
  68.         map.remove(key);
  69.     }
  70.     /**
  71.      * 获取缓存大小
  72.      * @param key
  73.      */
  74.     public static int getCacheSize(){
  75.         return map.size();
  76.     }
  77.     /**
  78.      * 清除全部缓存
  79.      */
  80.     public static synchronized void clearCache(){
  81.         tempList.clear();
  82.         map.clear();
  83.         System.out.println(“clear cache”);
  84.     }
  85.     static class TimeoutTimerThread implements Runnable {
  86.         public void run(){
  87.             while(true){
  88.                 try {
  89.                     checkTime();
  90.                 } catch (Exception e) {
  91.                     e.printStackTrace();
  92.                 }
  93.             }
  94.         }
  95.         /**
  96.          * 过期缓存的具体处理方法
  97.          * @throws Exception
  98.          */
  99.         private void checkTime() throws Exception{
  100.             //”开始处理过期 “;
  101.             CacheEntity tce = null;
  102.             long timoutTime = 1000L;
  103.             //” 过期队列大小 : “+tempList.size());
  104.             if(1 > tempList.size()){
  105.                 System.out.println(“过期队列空,开始轮询”);
  106.                 timoutTime = 1000L;
  107.                 Thread.sleep(timoutTime);
  108.                 return;
  109.             }
  110.             tce = tempList.get(0);
  111.             timoutTime = tce.getTimeoutStamp() – System.currentTimeMillis();
  112.             //” 过期时间 : “+timoutTime);
  113.             if(0 < timoutTime){
  114.                 //设定过期时间
  115.                 Thread.sleep(timoutTime);
  116.                 return;
  117.             }
  118.             System.out.print(” 清除过期缓存 : “+tce.getCacheKey());
  119.             //清除过期缓存和删除对应的缓存队列
  120.             tempList.remove(tce);
  121.             removeCache(tce.getCacheKey());
  122.         }
  123.     }
  124. }
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方式

  1. package com.cttc.cache.handler;
  2. import java.util.HashMap;
  3. import java.util.Timer;
  4. import java.util.TimerTask;
  5. import com.cttc.cache.entity.CacheEntity;
  6. import com.cttc.cache.entity.SimpleConcurrentMap;
  7. /**
  8. * @projName:WZServer
  9. * @className:CacheHandler
  10. * @description:缓存操作类,对缓存进行管理,清除方式采用Timer定时的方式
  11. * @creater:Administrator
  12. * @creatTime:2013年7月22日 上午9:18:54
  13. * @alter:Administrator
  14. * @alterTime:2013年7月22日 上午9:18:54
  15. * @remark:
  16. * @version
  17. */
  18. public class CacheTimerHandler {
  19.     private static final long SECOND_TIME = 1000;//默认过期时间 20秒
  20.     private static final int DEFUALT_VALIDITY_TIME = 20;//默认过期时间 20秒
  21.     private static final Timer timer ;
  22.     private static final SimpleConcurrentMap<String, CacheEntity> map;
  23.     static{
  24.         timer = new Timer();
  25.         map = new SimpleConcurrentMap<String, CacheEntity>(new HashMap<String, CacheEntity>(1<<18));
  26.     }
  27.     /**
  28.      * 增加缓存对象
  29.      * @param key
  30.      * @param ce
  31.      */
  32.     public static void addCache(String key, CacheEntity ce){
  33.         addCache(key, ce, DEFUALT_VALIDITY_TIME);
  34.     }
  35.     /**
  36.      * 增加缓存对象
  37.      * @param key
  38.      * @param ce
  39.      * @param validityTime 有效时间
  40.      */
  41.     public static synchronized void addCache(String key, CacheEntity ce, int validityTime){
  42.         map.put(key, ce);
  43.         //添加过期定时
  44.         timer.schedule(new TimeoutTimerTask(key), validityTime * SECOND_TIME);
  45.     }
  46.     /**
  47.      * 获取缓存对象
  48.      * @param key
  49.      * @return
  50.      */
  51.     public static synchronized CacheEntity getCache(String key){
  52.         return map.get(key);
  53.     }
  54.     /**
  55.      * 检查是否含有制定key的缓冲
  56.      * @param key
  57.      * @return
  58.      */
  59.     public static synchronized boolean isConcurrent(String key){
  60.         return map.containsKey(key);
  61.     }
  62.     /**
  63.      * 删除缓存
  64.      * @param key
  65.      */
  66.     public static synchronized void removeCache(String key){
  67.         map.remove(key);
  68.     }
  69.     /**
  70.      * 获取缓存大小
  71.      * @param key
  72.      */
  73.     public static int getCacheSize(){
  74.         return map.size();
  75.     }
  76.     /**
  77.      * 清除全部缓存
  78.      */
  79.     public static synchronized void clearCache(){
  80.         if(null != timer){
  81.             timer.cancel();
  82.         }
  83.         map.clear();
  84.         System.out.println(“clear cache”);
  85.     }
  86.     /**
  87.      * @projName:WZServer
  88.      * @className:TimeoutTimerTask
  89.      * @description:清除超时缓存定时服务类
  90.      * @creater:Administrator
  91.      * @creatTime:2013年7月22日 上午9:34:39
  92.      * @alter:Administrator
  93.      * @alterTime:2013年7月22日 上午9:34:39
  94.      * @remark:
  95.      * @version
  96.      */
  97.     static class TimeoutTimerTask extends TimerTask{
  98.         private String ceKey ;
  99.         public TimeoutTimerTask(String key){
  100.             this.ceKey = key;
  101.         }
  102.         @Override
  103.         public void run() {
  104.             CacheTimerHandler.removeCache(ceKey);
  105.             System.out.println(“remove : “+ceKey);
  106.         }
  107.     }
  108. }
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