现在的项目中应该基本都用redis做缓存了,本文提供一个简单的线程安全缓存类,提供超时淘汰策略。方便没必要引进第三方缓存时使用。
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* 一个简单的基于时间淘汰的缓存-线程安全
*
* @author cosmozhu
* @mail zhuchao1103@gmail.com
* @site https://www.cosmozhu.fun
*/
public class NormalCache {
private final static Map<Object, NormalCache.Entry> cache = new ConcurrentHashMap<Object, NormalCache.Entry>(16);
// 超时时间单位是秒
private static int timeout = -1;
// 检查缓存周期单位是秒
private static int checkCycle = 60;
private NormalCache() {
}
static {
Thread daemonThread = new Thread(() -> {
while (true) {
try {
TimeUnit.SECONDS.sleep(checkCycle);
for (Map.Entry<Object, NormalCache.Entry> entry : cache.entrySet()) {
// 淘汰数据
eliminate(entry.getKey(), entry.getValue(), entry.getValue().timeStamp);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
daemonThread.setDaemon(true);
daemonThread.setName("NormalCache Daemon Thread");
daemonThread.start();
}
private static void eliminate(Object key, NormalCache.Entry value, LocalDateTime timeStamp) {
if (timeout > 0 && !value.isHold && LocalDateTime.now().compareTo(timeStamp.plusSeconds(timeout)) > 0) {
cache.remove(key);
}
}
/**
* 放入缓存数据
*
* @param key 缓存键
* @param value 缓存数据
*/
public static <K, V> void put(K key, V value) {
cache.put(key, new NormalCache.Entry<V>(LocalDateTime.now(), value, false));
}
/**
* 放入缓存数据-不会被超时淘汰
*
* @param key 缓存键
* @param value 缓存数据
*/
public static <K, V> void putHold(K key, V value) {
cache.put(key, new NormalCache.Entry<V>(LocalDateTime.now(), value, true));
}
public static <K, V> V get(K key) {
NormalCache.Entry entry = cache.get(key);
eliminate(key, entry, entry.timeStamp);
return (V) cache.get(key).value;
}
public static <K, V> V remove(K key) {
return (V) cache.remove(key).value;
}
/**
* 获取数据超时时间
*
* @return
*/
public static int getTimeout() {
return timeout;
}
/**
* 设置数据超时时间-单位为s
*
* @param timeout 超时时间应设置大于0的数,默认为-1不进行数据淘汰
*/
public static void setTimeout(int timeout) {
NormalCache.timeout = timeout;
}
/**
* 获取缓存过期数据检查周期单位为秒
*
* @return 缓存过期数据检查周期单位为秒
*/
public static int getCheckCycle() {
return checkCycle;
}
/**
* 设置缓存过期数据检查周期单位为秒
*
* @param checkCycle 设置缓存过期数据检查周期单位为秒-整数
*/
public static void setCheckCycle(int checkCycle) {
NormalCache.checkCycle = checkCycle;
}
private static class Entry<V> {
private LocalDateTime timeStamp;
private V value;
private boolean isHold;
public Entry(LocalDateTime timeStamp, V value, boolean isHold) {
this.timeStamp = timeStamp;
this.value = value;
this.isHold = isHold;
}
@Override
public String toString() {
return "entry [timeStamp=" + timeStamp + ", value=" + value + "]";
}
}
}
作者:cosmozhu --90后的老父亲,专注于保护地球的程序员
欢迎转载,转载时请注明出处。