Java Web框架 缓存 Cache ReentrantReadWriteLock 定时器 TimerTask

Java Web框架 缓存 Cache ReentrantReadWriteLock 定时器 TimerTask

1、通过ReentrantReadWriteLock、ConcurrentHashMap实现一个简易缓存。

2、通过TimerTask或Thread回收缓存。

package mvc.framework.cache;

import java.util.LinkedList;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// 缓存管理器
public class CacheManager {
  
  private static final Logger LOGGER = LoggerFactory.getLogger(CacheManager.class);
  
  private CacheManager() {
    }
  
  // 缓存清理周期
  private long evictionIntervalTimer = 1 * 60 * 1000L;

    // 是否开启清除失效缓存
    private volatile Boolean clearExpireCacheEnable = true;

    // 缓存失效时间
    private long cacheTimeout = 12 * 60 * 60 * 1000L;

    // 缓存使用记录 LRU(Least recently used)最近最少使用算法
    private static LinkedList<Object> cacheLruList = new LinkedList<>();

    // 缓存池容量
    private static Integer cacheMaxSize = 1024;
    
    // 缓存池
    private final static Map<Object, CacheEntry> cacheHashMap = new ConcurrentHashMap<>();

    // 读写锁
    private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private static Lock writeLock = reentrantReadWriteLock.writeLock();
    private static Lock readLock = reentrantReadWriteLock.readLock();

    @SuppressWarnings("unused")
  private void init() {
        initClearTask();
    }
    
    // 自定义缓存失效时间
  @SuppressWarnings("unused")
    private void init(long cacheTimes) {
        this.cacheTimeout = cacheTimes;
        initClearTask();
    }

    private void initClearTask() {
        // 启动清除失效缓存数据
        if (clearExpireCacheEnable) {
        	// 线程Thread方式
            //new ClearCacheTask().start();
        	
        	// 定时器TimerTask方式
        	Timer timer = new Timer();  
        	ClearTimerTask timerTask = new ClearTimerTask();  
            // 程序运行后,延迟15秒执行,每隔evictionIntervalTimer重复执行
            timer.schedule(timerTask, 15, evictionIntervalTimer);  
        }
    }

    // 缓存实例
    private static CacheManager getCacheManagerInstance() {
        return CacheManagerFactory.cacheManager;
    }

    // 缓存工厂
    private static class CacheManagerFactory {
        private static final CacheManager cacheManager = new CacheManager();
    }

    // 定时器TimerTask方式
    private class ClearTimerTask extends TimerTask {
    	
    	{
    		LOGGER.debug("ClearTimerTask init");
    	}
    	
    	@Override  
        public void run() {
      try {
        LOGGER.debug("ClearTimerTask exec");

        long now = System.currentTimeMillis();

        for (Object key : cacheHashMap.keySet()) {
          try {
            writeLock.lock();

            // 判断使用记录中的key是否已经被LRU清除
            if (!cacheLruList.contains(key)) {
              return;
            }

            CacheEntry entry = cacheHashMap.get(key);
            if (now - entry.lastTouchTime >= cacheTimeout) {
              cacheHashMap.remove(key);
              cacheLruList.remove(key);
              LOGGER.debug("remove key:" + key);
            }
          } finally {
            writeLock.unlock();
          }
        }

      } catch (Exception e) {
        LOGGER.debug(e.toString());
      }
    	}
    }
    
    // 线程Thread方式
    @SuppressWarnings("unused")
  private class ClearCacheTask extends Thread {
    	
    	{
    		LOGGER.debug("ClearCacheTask init");
    	}

        @Override
        public void run() {
            while (clearExpireCacheEnable) {
                try {
                	LOGGER.debug("ClearTimerTask exec");
                	
                    long now = System.currentTimeMillis();

                    // 定时清理
                    try {
                    	Thread.sleep(evictionIntervalTimer);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    for (Object key : cacheHashMap.keySet()) {
                    	try {
                            writeLock.lock();

                            // 判断使用记录中是否存在
                            if (!cacheLruList.contains(key)) {
                                return;
                            }

                            CacheEntry entry = cacheHashMap.get(key);
                            if (now - entry.lastTouchTime >= cacheTimeout) {
                                cacheHashMap.remove(key);
                                cacheLruList.remove(key);
                                LOGGER.debug("remove key:" + key);
                            }
                        } finally {
                            writeLock.unlock();
                        }
                    }

                } catch (Exception e) {
                	LOGGER.debug(e.toString());
                }
            }
        }
    }

    // CacheEntry实体
    private class CacheEntry {
        long lastTouchTime;

        Object value;

        CacheEntry(Object value) {
            super();
            this.value = value;
        }

    public void setLastTouchTime(long currentTimeMillis) {
      this.lastTouchTime = System.currentTimeMillis();
    }
    }


    // 赋值
    public Object put(Object key, Object value) throws Exception {

        // 判断缓存大小是否够用,否则根据LRU删除
        if (cacheHashMap.size() > cacheMaxSize) {
            delete();
        }

        CacheEntry entry = new CacheEntry(value);

        writeLock.lock();
        try {
            cacheHashMap.put(key, entry);
            cacheLruList.addFirst(key);
        } finally {
            writeLock.unlock();
        }
        return value;
    }
    
    // 取值
    public Object get(Object key) {

        readLock.lock();
        CacheEntry entry = null;
        try {
            entry = cacheHashMap.get(key);
        } finally {
            readLock.unlock();
        }
        
        if (entry == null) {
        	return null;
        }

        // 更新CacheEntry缓存访问时间
        updateCacheTime(entry);
        // 更新使用记录
        updateCacheLruList(key);

        return entry == null ? null : entry.value;
    }

    // 更新缓存访问时间
    public static void updateCacheTime(CacheEntry entry) {
        writeLock.lock();
        try {
            entry.setLastTouchTime(System.currentTimeMillis());
        } finally {
            writeLock.unlock();
        }

    }

    // 更新缓存使用记录
    public static void updateCacheLruList(Object key) {

        writeLock.lock();
        try {
            // 删除使用记录
            cacheLruList.remove(key);
            // 新增使用记录到首位
            cacheLruList.addFirst(key);
        } finally {
            writeLock.unlock();
        }
    }

    // 删除最近最少使用的缓存
    public static void delete() {

        Object cacheKey = null;
        writeLock.lock();
        try {
            cacheKey = cacheLruList.get(cacheLruList.size() - 1);
            cacheLruList.remove(cacheLruList.size() - 1);
            cacheHashMap.remove(cacheKey);
            LOGGER.debug("lru remove key:" + cacheKey);
        } finally {
            writeLock.unlock();
        }
    }

    // 删除
    public static void delete(Object key) {

        if (key == null)
            return;

        writeLock.lock();
        try {
            cacheHashMap.remove(key);
            cacheLruList.remove(key);
        } finally {
            writeLock.unlock();
        }
    }

    // 清空
    public static void clear() {

        writeLock.lock();
        try {
            cacheHashMap.clear();
            cacheLruList.clear();
        } finally {
            writeLock.unlock();
        }
    }

    // 测试
    public static void main(String[] args) throws Exception {
        CacheManager cacheManager = CacheManager.getCacheManagerInstance();
        //cacheManager.init(3 * 60 * 1000L);
        cacheManager.init();

        for (int i = 0; i < 10; i++) {
            cacheManager.put(i, i);
        }
        
        cacheManager.get(1);
        cacheManager.get(3);
    }
}

 

发表回复

您的电子邮箱地址不会被公开。