基于Caffeine再次封装的本地缓存工具
引入maven依赖
caffeine、hutool、lombok
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
复制工具类代码
import cn.hutool.core.lang.Assert;
import com.github.benmanes.caffeine.cache.*;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author: humorchen
* date: 2023/11/21
* description: Caffeine本地缓存创建工具,建议使用该工具进行缓存对象构建
**/
@Setter
@Accessors(chain = true)
public class LocalCacheUtil<K, V> {
/**
* 线程池初始线程数 默认值,无任务执行不占用CPU
*/
private static final int DEFAULT_THREAD = 4;
/**
* 线程池最大线程数 默认值
*/
private final int DEFAULT_MAX_THREAD = 128;
/**
* 线程池额外线程数存活时间 默认值
*/
private final int DEFAULT_THREAD_KEEP_ALIVE = 10;
/**
* 线程池额外线程数存活时间单位 默认值
*/
private final TimeUnit DEFAULT_THREAD_KEEP_ALIVE_TIMEUNIT = TimeUnit.MINUTES;
/**
* 线程池拒绝策略 默认值
*/
private final RejectedExecutionHandler DEFAULT_THREAD_EXECUTOR_ABORT_POLICY = new ThreadPoolExecutor.AbortPolicy();
/**
* 初始化缓存容量默认值
*/
private final int DEFAULT_INIT_CAPACITY = 128;
/**
* 缓存最大容量默认值
*/
private final int DEFAULT_MAX_CAPACITY = 4096;
/**
* 线程池等待队列的容量默认值 用的链表不用担心浪费内存
*/
private final int DEFAULT_BLOCKING_QUEUE_SIZE = 4096;
/**
* 缓存写入后n秒过期 默认值
*/
private final int DEFAULT_EXPIRE_AFTER_WRITE = 6;
/**
* 缓存写入3秒后一旦有访问,就异步更新这个缓存值 默认值
*/
private final int DEFAULT_REFRESH_AFTER_WRITE = 3;
/**
* 缓存的时间单位
*/
private final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;
/**
* Caffeine缓存名称,用于做线程名,打印等
*/
private String cacheName;
/**
* 线程计数
*/
private AtomicInteger threadNum = new AtomicInteger(0);
/**
* 线程池初始线程数
*/
private int thread = DEFAULT_THREAD;
/**
* 线程池最大线程数
*/
private int maxThread = DEFAULT_MAX_THREAD;
/**
* 线程池额外线程数存活时间
*/
private int threadKeepAlive = DEFAULT_THREAD_KEEP_ALIVE;
/**
* 线程池额外线程数存活时间单位
*/
private TimeUnit threadKeepAliveTimeunit = DEFAULT_THREAD_KEEP_ALIVE_TIMEUNIT;
/**
* 线程池拒绝策略
*/
private final RejectedExecutionHandler threadExecutorAbortPolicy = DEFAULT_THREAD_EXECUTOR_ABORT_POLICY;
/**
* 初始化缓存容量
*/
private int initCapacity = DEFAULT_INIT_CAPACITY;
/**
* 缓存最大容量
*/
private int maxCapacity = DEFAULT_MAX_CAPACITY;
/**
* 线程池等待队列的容量
*/
private int blockingQueueSize = DEFAULT_BLOCKING_QUEUE_SIZE;
/**
* 缓存写入后n秒过期
*/
private Integer expireAfterWrite;
/**
* 缓存访问后n秒过期
*/
private Integer expireAfterAccess;
/**
* 缓存写入3秒后一旦有访问,就异步更新这个缓存值
*/
private Integer refreshAfterWrite;
/**
* 缓存时间单位
*/
private TimeUnit timeUnit = DEFAULT_TIME_UNIT;
/**
* 移除key的监听器
*/
private RemovalListener<? super K, ? super V> removalListener;
/**
* 调度器
*/
private Scheduler scheduler;
/**
* 当前构建的caffeine对象
*/
private Caffeine<K, V> sourceCaffeineBuilder;
private LocalCacheUtil(String cacheName) {
this.cacheName = cacheName;
}
/**
* 新建一个caffeine缓存构建器
*
* @param cacheName 缓存名称(用于线程名,日志打印)
* @return
*/
public static LocalCacheUtil<Object, Object> newCacheBuilder(String cacheName) {
LocalCacheUtil<Object, Object> builder = new LocalCacheUtil<>(cacheName);
builder.sourceCaffeineBuilder = Caffeine.newBuilder();
return builder;
}
/**
* 获取原生caffeine builder修改非常用配置
*
* @return
*/
public Caffeine<K, V> getRawCaffeineBuilder() {
return this.sourceCaffeineBuilder;
}
/**
* 简单缓存
*
* @param initCapacity
* @param maxCapacity
* @param expireSecond
* @return
*/
public LocalCacheUtil<K, V> basicCacheConfig(int initCapacity, int maxCapacity, int expireSecond) {
setInitCapacity(initCapacity);
setMaxCapacity(maxCapacity);
setExpireAfterWrite(expireSecond);
return this;
}
/**
* 简单缓存
*
* @param initCapacity
* @param maxCapacity
* @param expireSecond
* @param refreshAfterWrite 多久更新缓存数据,build的时候要传入加载方法
* @return
*/
public LocalCacheUtil<K, V> basicAutoRefreshCacheConfig(int initCapacity, int maxCapacity, int expireSecond, int refreshAfterWrite) {
setInitCapacity(initCapacity);
setMaxCapacity(maxCapacity);
setExpireAfterWrite(expireSecond);
setRefreshAfterWrite(refreshAfterWrite);
return this;
}
/**
* 简单数据的缓存,待自动刷新
*
* @param initCapacity
* @param maxCapacity
* @param expireSecond
* @param refreshAfterWrite
* @return
*/
public LocalCacheUtil<K, V> basicAutoRefreshCacheConfigWithSingleExecutor(int initCapacity, int maxCapacity, int expireSecond, int refreshAfterWrite) {
LocalCacheUtil<K, V> util = this.basicAutoRefreshCacheConfig(initCapacity, maxCapacity, expireSecond, refreshAfterWrite);
util.setThread(1);
util.setMaxThread(4);
util.setBlockingQueueSize(16);
return util;
}
/**
* 构建不带加载器的cache
* @return
* @param <K1>
* @param <V1>
*/
public <K1 extends K, V1 extends V> Cache<K1, V1> build() {
return this.build(null);
}
/**
* 构建最终的缓存对象
*
* @return Cache
*/
public <K1 extends K, V1 extends V> Cache<K1, V1> build(CacheLoader<K1, V1> cacheLoader) {
Caffeine<K, V> caffeine = this.sourceCaffeineBuilder.initialCapacity(initCapacity).maximumSize(maxCapacity);
// 必须设置过期时间
Assert.isFalse(expireAfterAccess == null && expireAfterWrite == null, () -> new IllegalArgumentException("expireAfterAccess和expireAfterWrite必须设置一个"));
int expireSecond = 1;
if (expireAfterWrite != null) {
caffeine.expireAfterWrite(expireAfterWrite, timeUnit);
expireSecond = expireAfterWrite;
}
if (expireAfterAccess != null) {
caffeine.expireAfterAccess(expireAfterAccess, timeUnit);
expireSecond = expireAfterAccess;
}
// 填充默认过期时间值并检查值
if (cacheLoader != null && refreshAfterWrite == null) {
refreshAfterWrite = Math.max(expireSecond / 2, 1);
Assert.isTrue(refreshAfterWrite < expireSecond, () -> new IllegalArgumentException("使用默认方案时过期时间请大于1秒"));
setRefreshAfterWrite(refreshAfterWrite);
}
if (refreshAfterWrite != null) {
Assert.notNull(cacheLoader, () -> new IllegalArgumentException("使用自动刷新必须提供加载器cacheLoader"));
caffeine.refreshAfterWrite(refreshAfterWrite, timeUnit);
}
if (scheduler != null) {
caffeine.scheduler(scheduler);
}
if (removalListener != null) {
caffeine.removalListener(removalListener);
}
ThreadFactory threadFactory = (runnable) -> {
String cacheName = "【本地缓存线程】" + this.cacheName + "-" + threadNum.incrementAndGet();
return new Thread(runnable, cacheName);
};
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(thread, maxThread, threadKeepAlive, threadKeepAliveTimeunit, new LinkedBlockingDeque<>(blockingQueueSize), threadFactory, threadExecutorAbortPolicy);
caffeine.executor(threadPoolExecutor);
return cacheLoader == null ? caffeine.build() : caffeine.build(cacheLoader);
}
}
使用示范
···java
/**
* http param动态更新缓存
/
private Cache<String, RecoveryRequest> httpParamCache = LocalCacheUtil.newCacheBuilder(“VivoController-httpParamCache”).basicAutoRefreshCacheConfig(4, 4, 120, 60).build((k) -> vivoService.getHttpParam());
/*
* vivo查询接口动态更新的缓存 selectVivoExternalModelCache
*/
private Cache<ViVoRequest, ViVoResponse> selectVivoExternalModelCache = LocalCacheUtil.newCacheBuilder(“VivoControllerGateway-selectVivoExternalModel”).basicAutoRefreshCacheConfig(512, 4096, 10, 5).build(k -> vivoService.selectVivoExternalModel(k));
本文来自博客园,作者:HumorChen99,转载请注明原文链接:https://www.cnblogs.com/HumorChen/p/18039438