Java实现一个简单的缓存方法


缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。

创建缓存对象EntityCache.java

public class EntityCache {
   /**
    * 保存的数据
    */
   private Object datas;
 
   /**
    * 设置数据失效时间,为0表示永不失效
    */
   private long timeOut;
 
   /**
    * 最后刷新时间
    */
   private long lastRefeshTime;
 
   public EntityCache(Object datas, long timeOut, long lastRefeshTime) {
     this .datas = datas;
     this .timeOut = timeOut;
     this .lastRefeshTime = lastRefeshTime;
   }
   public Object getDatas() {
     return datas;
   }
   public void setDatas(Object datas) {
     this .datas = datas;
   }
   public long getTimeOut() {
     return timeOut;
   }
   public void setTimeOut( long timeOut) {
     this .timeOut = timeOut;
   }
   public long getLastRefeshTime() {
     return lastRefeshTime;
   }
   public void setLastRefeshTime( long lastRefeshTime) {
     this .lastRefeshTime = lastRefeshTime;
   }
 
 
}
定义缓存操作接口,ICacheManager.java
public interface ICacheManager {
   /**
    * 存入缓存
    * @param key
    * @param cache
    */
   void putCache(String key, EntityCache cache);
 
   /**
    * 存入缓存
    * @param key
    * @param cache
    */
   void putCache(String key, Object datas, long timeOut);
 
   /**
    * 获取对应缓存
    * @param key
    * @return
    */
   EntityCache getCacheByKey(String key);
 
   /**
    * 获取对应缓存
    * @param key
    * @return
    */
   Object getCacheDataByKey(String key);
 
   /**
    * 获取所有缓存
    * @param key
    * @return
    */
   Map<String, EntityCache> getCacheAll();
 
   /**
    * 判断是否在缓存中
    * @param key
    * @return
    */
   boolean isContains(String key);
 
   /**
    * 清除所有缓存
    */
   void clearAll();
 
   /**
    * 清除对应缓存
    * @param key
    */
   void clearByKey(String key);
 
   /**
    * 缓存是否超时失效
    * @param key
    * @return
    */
   boolean isTimeOut(String key);
 
   /**
    * 获取所有key
    * @return
    */
   Set<String> getAllKeys();
}

实现接口ICacheManager,CacheManagerImpl.java

这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。

public class CacheManagerImpl implements ICacheManager {
   private static Map<String, EntityCache> caches = new ConcurrentHashMap<String, EntityCache>();
 
   /**
    * 存入缓存
    * @param key
    * @param cache
    */
   public void putCache(String key, EntityCache cache) {
     caches.put(key, cache);
   }
 
   /**
    * 存入缓存
    * @param key
    * @param cache
    */
   public void putCache(String key, Object datas, long timeOut) {
     timeOut = timeOut > 0 ? timeOut : 0L;
     putCache(key, new EntityCache(datas, timeOut, System.currentTimeMillis()));
   }
 
   /**
    * 获取对应缓存
    * @param key
    * @return
    */
   public EntityCache getCacheByKey(String key) {
     if ( this .isContains(key)) {
       return caches.get(key);
     }
     return null ;
   }
 
   /**
    * 获取对应缓存
    * @param key
    * @return
    */
   public Object getCacheDataByKey(String key) {
     if ( this .isContains(key)) {
       return caches.get(key).getDatas();
     }
     return null ;
   }
 
   /**
    * 获取所有缓存
    * @param key
    * @return
    */
   public Map<String, EntityCache> getCacheAll() {
     return caches;
   }
 
   /**
    * 判断是否在缓存中
    * @param key
    * @return
    */
   public boolean isContains(String key) {
     return caches.containsKey(key);
   }
 
   /**
    * 清除所有缓存
    */
   public void clearAll() {
     caches.clear();
   }
 
   /**
    * 清除对应缓存
    * @param key
    */
   public void clearByKey(String key) {
     if ( this .isContains(key)) {
       caches.remove(key);
     }
   }
 
   /**
    * 缓存是否超时失效
    * @param key
    * @return
    */
   public boolean isTimeOut(String key) {
     if (!caches.containsKey(key)) {
       return true ;
     }
     EntityCache cache = caches.get(key);
     long timeOut = cache.getTimeOut();
     long lastRefreshTime = cache.getLastRefeshTime();
     if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime >= timeOut) {
       return true ;
     }
     return false ;
   }
 
   /**
    * 获取所有key
    * @return
    */
   public Set<String> getAllKeys() {
     return caches.keySet();
   }
}
CacheListener.java,监听失效数据并移除。
public class CacheListener{
   Logger logger = Logger.getLogger( "cacheLog" );
   private CacheManagerImpl cacheManagerImpl;
   public CacheListener(CacheManagerImpl cacheManagerImpl) {
     this .cacheManagerImpl = cacheManagerImpl;
   }
 
   public void startListen() {
     new Thread(){
       public void run() {
         while ( true ) {
           for (String key : cacheManagerImpl.getAllKeys()) {
             if (cacheManagerImpl.isTimeOut(key)) {
              cacheManagerImpl.clearByKey(key);
              logger.info(key + "缓存被清除" );
            }
           }
         }
       }
     }.start();
 
   }
}
测试类TestCache.java
public class TestCache {
   Logger logger = Logger.getLogger( "cacheLog" );
   /**
    * 测试缓存和缓存失效
    */
   @Test
   public void testCacheManager() {
     CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();
     cacheManagerImpl.putCache( "test" , "test" , 10 * 1000L);
     cacheManagerImpl.putCache( "myTest" , "myTest" , 15 * 1000L);
     CacheListener cacheListener = new CacheListener(cacheManagerImpl);
     cacheListener.startListen();
     logger.info( "test:" + cacheManagerImpl.getCacheByKey( "test" ).getDatas());
     logger.info( "myTest:" + cacheManagerImpl.getCacheByKey( "myTest" ).getDatas());
     try {
       TimeUnit.SECONDS.sleep( 20 );
     } catch (InterruptedException e) {
       e.printStackTrace();
     }
     logger.info( "test:" + cacheManagerImpl.getCacheByKey( "test" ));
     logger.info( "myTest:" + cacheManagerImpl.getCacheByKey( "myTest" ));
   }
 
   /**
    * 测试线程安全
    */
   @Test
   public void testThredSafe() {
     final String key = "thread" ;
     final CacheManagerImpl cacheManagerImpl = new CacheManagerImpl();
     ExecutorService exec = Executors.newCachedThreadPool();
     for ( int i = 0 ; i < 100 ; i++) {
       exec.execute( new Runnable() {
         public void run() {
             if (!cacheManagerImpl.isContains(key)) {
               cacheManagerImpl.putCache(key, 1 , 0 );
             } else {
               //因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来
               synchronized (cacheManagerImpl) {
                 int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1 ;
                 cacheManagerImpl.putCache(key,value , 0 );
               }
             }
         }
       });
     }
     exec.shutdown();
     try {
       exec.awaitTermination( 1 , TimeUnit.DAYS);
     } catch (InterruptedException e1) {
       e1.printStackTrace();
     }
 
     logger.info(cacheManagerImpl.getCacheDataByKey(key).toString());
   }
}
 
 
来源:http://www.jb51.net/article/111518.htm


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM