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);
}
}