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