引入依赖:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.6</version>
</dependency>
使用方式
import org.apache.groovy.util.concurrent.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import org.apache.groovy.util.concurrent.concurrentlinkedhashmap.Weighers;
public class TestLinkHashMap {
/**
* 集合的最大数量2个
*/
public static ConcurrentLinkedHashMap<String, String> cache = new ConcurrentLinkedHashMap.Builder<String, String>()
.maximumWeightedCapacity(2).weigher(Weighers.singleton()).build();
public static void main(String[] args) {
lru();
}
public static void lru() {
cache.put("aa", "aa");
cache.put("bb", "bb");
//aa最新使用
String aa = cache.get("aa");
cache.put("cc", "cc");
System.out.println("aa:" + cache.get("aa"));
System.out.println("bb:" + cache.get("bb"));
}
}
输出:
aa:aa
bb:null
集合的大小为2个,因为aa是最新访问。到存入cc时,bb就会失效。即实现了LRU算法。
扩展:实现内存缓存
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Type;
import java.util.function.Supplier;
/**
* 缓存管理器
*
* @author by yexuerui
* @Date 2021-05-26 16:09
*/
public interface CacheManager {
/**
* 失效时间的比例。
* 缓存的失效时间=申请的有效时间*expireRate
*/
double expireRate = 0.75;
/**
* 填充缓存的值
*
* @param key 缓存的key
* @param value 缓存的value
* @param time 失效时间,单位ms
*/
void put(String key, String value, long time);
/**
* 获取缓存的的值
*
* @param key 缓存的key
* @return 缓存的值
*/
String get(String key);
/**
* 移除缓存的的值
*
* @param key 缓存的key
*/
void remove(String key);
/**
* 在缓存中获取值
*
* @param supplier 回调的逻辑代码
* @param key 缓存的key
* @param time 失效时间,ms
* @param isCache 是否执行缓存
* @param type 缓存的值反序列化的类型。
* {@code Type type = new TypeReference<User>(){}.getType();}
* @param <T>
* @return
*/
default <T> T getInCache(Supplier<T> supplier, String key, long time, boolean isCache, Type type) {
//获取cache的key
T result;
if (isCache) {
String v = get(key);
if (v == null) {
result = supplier.get();
if (result != null) {
put(key, JSON.toJSONString(result), Math.round(time * expireRate));
}
} else {
result = JSON.parseObject(v, type);
}
} else {
result = supplier.get();
}
return result;
}
}
import lombok.Getter;
import org.apache.groovy.util.concurrent.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import org.apache.groovy.util.concurrent.concurrentlinkedhashmap.Weighers;
import org.springframework.beans.factory.InitializingBean;
import java.util.concurrent.*;
/**
* 内存级别的缓存。
* 为了防止占用内存过大,故采用LRU算法维护缓存。
*
* @author by yexuerui
* @Date 2021-05-26 16:14
*/
public class MemoryCacheManager implements CacheManager, InitializingBean {
ConcurrentLinkedHashMap<String, CacheData> cache = new ConcurrentLinkedHashMap.Builder<String, CacheData>()
.maximumWeightedCapacity(500).weigher(Weighers.singleton())
.build();
/**
* 存储缓存,填充数据的策略为覆盖
*
* @param key 缓存的key
* @param value 缓存的value
* @param time 失效时间,单位ms
*/
@Override
public void put(String key, String value, long time) {
cache.put(key, new CacheData(value, System.currentTimeMillis() + time));
}
/**
* 获取缓存的值
*
* @param key 缓存的key
* @return 缓存的值
*/
@Override
public String get(String key) {
CacheData cacheData = cache.get(key);
String value = null;
//校验数据
if (cacheData != null) {
//数据过期,手动移除
if (System.currentTimeMillis() >= cacheData.expire) {
cache.remove(key);
value = null;
} else {
value = cacheData.getValue();
}
}
return value;
}
/**
* 移除缓存的值
*
* @param key 缓存的key
*/
@Override
public void remove(String key) {
cache.remove(key);
}
@Override
public void afterPropertiesSet() throws Exception {
//初始化定时器
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
Thread thread = new Thread(runnable, "cache");
thread.setDaemon(true);
return thread;
});
scheduler.scheduleAtFixedRate(() -> {
cache.forEach((k, v) -> {
//判断是否失效
if (System.currentTimeMillis() >= v.expire) {
cache.remove(k);
}
});
}, 0, 5, TimeUnit.SECONDS);
}
@Getter
static class CacheData {
/**
* 存储的值
*/
private String value;
/**
* 失效时间戳,单位ms
*/
private long expire;
public CacheData(String value, long expire) {
this.value = value;
this.expire = expire;
}
}
}