原文链接
CSDN: https://blog.csdn.net/qq_35030994/article/details/80871279
修改了以下内容
- 将定时扫描过期Key的任务使用Spring注解
@Scheduled
的cron实现 - 将Cache改变为支持泛型,调整为单例模式。
Cache源代码
package cn.anytec.cloud.bus.utils;
import cn.anytec.cloud.bus.service.ScheduledService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Cache缓存
* @author imyzt
*/
public class Cache<K, V> {
private static Logger LOGGER = LoggerFactory.getLogger(Cache.class);
/**
* 缓存最大个数
*/
private static final Integer CACHE_MAX_NUMBER = Constant.DEFAULT_CACHE_MAX_NUMBER;
/**
* 当前缓存个数
*/
private static Integer CURRENT_SIZE = 0;
/**
* 缓存对象
*/
private final Map<K, CacheObj<V>> CACHE_OBJECT_MAP = new ConcurrentHashMap<>();
/**
* 这个记录了缓存使用的最后一次的记录,最近使用的在最前面
*/
private final List<K> CACHE_USE_LOG_LIST = new LinkedList<>();
/**
* 默认Key
*/
private final String DEFAULT_VALUE = "DEFAULT_VALUE";
private Cache() { }
private static Cache cache = new Cache();
public static Cache defaultCache() {
return cache;
}
/**
* 设置缓存
*/
public void set(K cacheKey, V cacheValue, long cacheTime) {
Long ttlTime = null;
if (cacheTime <= 0L) {
if (cacheTime == -1L) {
ttlTime = -1L;
} else {
return;
}
}
checkSize();
saveCacheUseLog(cacheKey);
CURRENT_SIZE = CURRENT_SIZE + 1;
if (ttlTime == null) {
ttlTime = System.currentTimeMillis() + cacheTime;
}
CacheObj<V> cacheObj = new CacheObj(cacheValue, ttlTime);
CACHE_OBJECT_MAP.put(cacheKey, cacheObj);
LOGGER.info("have set key :" + cacheKey);
}
/**
* 设置缓存
*/
public void set(K cacheKey, V cacheValue) {
set(cacheKey, cacheValue, -1L);
}
/**
* 设置缓存
*/
public void set(K cacheKey, long cacheTime) {
set(cacheKey, (V) DEFAULT_VALUE, cacheTime);
}
/**
* 获取缓存
*/
public Object get(K cacheKey) {
if (checkCache(cacheKey)) {
saveCacheUseLog(cacheKey);
return CACHE_OBJECT_MAP.get(cacheKey).getCacheValue();
}
return null;
}
/**
* 是否包含某一个Key值
* @param cacheKey
* @return
*/
public boolean containsKey(K cacheKey) {
return checkCache(cacheKey);
}
/**
* 删除所有缓存
*/
public void clear() {
LOGGER.info("have clean all key !");
CACHE_OBJECT_MAP.clear();
CURRENT_SIZE = 0;
}
/**
* 删除某个缓存
*/
public void del(K cacheKey) {
Object cacheValue = CACHE_OBJECT_MAP.remove(cacheKey);
if (cacheValue != null) {
LOGGER.info("have delete key :" + cacheKey);
CURRENT_SIZE = CURRENT_SIZE - 1;
}
}
/**
* 判断缓存在不在,过没过期
*/
private boolean checkCache(K cacheKey) {
CacheObj cacheObj = CACHE_OBJECT_MAP.get(cacheKey);
if (cacheObj == null) {
return false;
}
if (cacheObj.getTtlTime() == -1L) {
return true;
}
if (cacheObj.getTtlTime() < System.currentTimeMillis()) {
del(cacheKey);
return false;
}
return true;
}
/**
* 删除最近最久未使用的缓存
*/
private void deleteLRU() {
LOGGER.info("delete Least recently used run!");
K cacheKey = CACHE_USE_LOG_LIST.remove(CACHE_USE_LOG_LIST.size() - 1);
del(cacheKey);
}
/**
* 删除过期的缓存
* 禁止手动调用! 由定时任务定时拉起
* @see ScheduledService#deleteTimeOut()
*/
public void deleteTimeOut() {
LOGGER.info("delete time out run!");
List<K> deleteKeyList = new LinkedList<>();
for(Map.Entry<K, CacheObj<V>> entry : CACHE_OBJECT_MAP.entrySet()) {
if (entry.getValue().getTtlTime() < System.currentTimeMillis() && entry.getValue().getTtlTime() != -1L) {
deleteKeyList.add(entry.getKey());
}
}
for (K deleteKey : deleteKeyList) {
del(deleteKey);
}
LOGGER.info("delete cache count is :" + deleteKeyList.size());
}
/**
* 检查大小
* 当当前大小如果已经达到最大大小
* 首先删除过期缓存,如果过期缓存删除过后还是达到最大缓存数目
* 删除最久未使用缓存
*/
private void checkSize() {
if (CURRENT_SIZE >= CACHE_MAX_NUMBER) {
deleteTimeOut();
}
if (CURRENT_SIZE >= CACHE_MAX_NUMBER) {
deleteLRU();
}
}
/**
* 保存缓存的使用记录
*/
private synchronized void saveCacheUseLog(K cacheKey) {
CACHE_USE_LOG_LIST.remove(cacheKey);
CACHE_USE_LOG_LIST.add(0, cacheKey);
}
public void showUtilsInfo() {
System.out.println("cache max count is :" + CACHE_MAX_NUMBER);
System.out.println("cache current count is :" + CURRENT_SIZE);
System.out.println("cache object map is :" + CACHE_OBJECT_MAP.toString());
System.out.println("cache use log list is :" + CACHE_USE_LOG_LIST.toString());
}
}
class CacheObj<V> {
/**
* 缓存对象
*/
private V cacheValue;
/**
* 缓存过期时间
*/
private Long ttlTime;
CacheObj(V cacheValue, Long ttlTime) {
this.cacheValue = cacheValue;
this.ttlTime = ttlTime;
}
Object getCacheValue() {
return cacheValue;
}
Long getTtlTime() {
return ttlTime;
}
@Override
public String toString() {
return "CacheObj{" +
"cacheValue=" + cacheValue +
", ttlTime=" + ttlTime +
'}';
}
}
定时任务
@Component
public class ScheduledService {
@Scheduled(cron = "${bus.cache-delete-cycle}")
public void deleteTimeOut() {
Cache.defaultCache().deleteTimeOut();
}
}