package com.example.riverside.util.cache;
import com.example.riverside.util.Spring.PropertiesLoaderUtils;
import com.example.riverside.util.invoke.StreamScheduleInvokeInterface;
import com.example.riverside.util.stream.StreamUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 缓存区
* @author tzy
* @date 2023年4月25日10:30:21
* @version 2.1
*/
@Slf4j
@Component
public class CacheDistrict {
public final static long effectiveTimeDefault = 1000 * 60 * 15; // 15分钟
public final static boolean effectiveTimerDefault = true;
private final AtomicBoolean atomicFlag = new AtomicBoolean(true);
/**
* @TODO cache.district.unification_overdue 配置其缓存有效模式<p>
* false: 为每个存在有效期的缓存值加计时器(能有效,准时的释放过期缓存,性能换空间)<p>
* true: 由缓存区统一管理有效期(不定期的检查过期缓存并释放,可手动检查过期缓存,空间换性能)
* (拓展:1.在GC前释放过期缓存 2.使用一个缓存区计时器)
*/
private static boolean effectiveTimer;
static {
try {
String effectiveTimerC = PropertiesLoaderUtils.getValue("cache.district.unification_overdue", "application.properties").toString();
effectiveTimer = Boolean.parseBoolean(effectiveTimerC);
} catch (Exception e) {
effectiveTimer = effectiveTimerDefault;
}
}
private final AutoSortMap<Long, String> autoSortMap = new AutoSortMap<>(Comparator.comparing(AutoSortMap.SortMap::getK));
private final Map<String, CacheIndividual<?>> cacheMap = new WeakHashMap<>();
public int size() {
return cacheMap.size();
}
public List<String> getAllKey() {
List<String> keyList = new ArrayList<>(cacheMap.size());
for(Map.Entry<String, CacheIndividual<?>> entry : cacheMap.entrySet()) {
keyList.add(entry.getKey());
}
return keyList;
}
public <T> T getCache(String key) throws Exception {
Object cache = getCacheImplement(key);
try {
return Objects.isNull(cache) ? null : (T) cache;
} catch (Exception e) {
throw new Exception("类型转换失败!" + e.getMessage());
}
}
public <T> T getCache(String key, T t) throws Exception {
Object cache = getCacheImplement(key);
try {
t = Objects.isNull(cache) ? null : (T) cache;
return t;
} catch (Exception e) {
throw new Exception("类型转换失败!" + e.getMessage());
}
}
private Object getCacheImplement(String key){
CacheIndividual<?> cacheIndividual = cacheMap.get(key);
if (Objects.isNull(cacheIndividual)) {
return null;
}
Object cache = cacheIndividual.get();
if (Objects.isNull(cache)) {
return null;
}
if (System.currentTimeMillis() > cacheIndividual.getExpireTime()) {
return null;
}
return cache;
}
public <T> void pushCache(String key, T t, long effectiveTime, String message) {
boolean flag = cacheMap.containsKey(key);
if (flag) {
// 覆盖
CacheIndividual<?> individual = cacheMap.get(key);
if (individual != null) individual.lapse();
individual = null;
} else {
// 新增
}
CacheIndividual<T> newIndividual = CacheIndividual.create(t, effectiveTime, message);
cacheMap.put(key, newIndividual);
this.overdueClear(key, newIndividual);
}
public <T> boolean pushCache(String key, T t, boolean judge, long effectiveTime, String message) {
boolean flag = cacheMap.containsKey(key);
if (flag) {
if (judge) {
// 覆盖
CacheIndividual<?> individual = cacheMap.get(key);
if (individual != null) individual.lapse();
individual = null;
CacheIndividual<T> newIndividual = CacheIndividual.create(t, effectiveTime, message);
cacheMap.put(key, newIndividual);
this.overdueClear(key, newIndividual);
return true;
} else {
// 已存在
return false;
}
} else {
// 新增
CacheIndividual<T> newIndividual = CacheIndividual.create(t, effectiveTime, message);
cacheMap.put(key, newIndividual);
this.overdueClear(key, newIndividual);
return true;
}
}
private <T> void overdueClear(String key, CacheIndividual<T> individual) {
if (effectiveTimer) {
districtOverdueClear(key, individual);
} else {
itemOverdueClear(key, individual);
}
}
private <T> void districtOverdueClear(String key, CacheIndividual<T> individual) {
// 加入自序图前,移除已存在的时间键值
autoSortMap.removeByValue(key);
autoSortMap.push(individual.getExpireTime(), key);
clearOverdue();
}
public void clearOverdue() {
if (atomicFlag.compareAndSet(true, false)) {
new Thread(() -> {
while (true) {
if (!autoSortMap.isEmpty()) {
AutoSortMap.SortMap<Long, String> sortMap = autoSortMap.first();
if (System.currentTimeMillis() > sortMap.getK()) {
String key = sortMap.getV();
CacheIndividual<?> individual = cacheMap.get(key);
autoSortMap.pollFirst();
release(key, individual);
} else {
break;
}
} else {
break;
}
}
atomicFlag.set(true);
}).start();
}
}
private <T> void itemOverdueClear(String key, CacheIndividual<T> individual) {
individual.setTimer(new Timer());
individual.getTimer().schedule(new TimerTask() {
@Override
public void run() {
release(key, individual);
}
}, individual.getEffectiveTime());
}
private <T> void release(String key, CacheIndividual<T> individual) {
autoSortMap.removeByValue(key);
cacheMap.remove(key);
if (individual == null) return;
log.warn("键:" + key + " 的缓存值已失效");
// 释放资源
individual.set(null);
if (individual.getTimer() != null) individual.getTimer().cancel();
individual.setTimer(null);
individual = null;
}
public void flushTime(String key) throws Exception {
CacheIndividual<?> individual = cacheMap.get(key);
if(individual.getTimer() != null){
individual.getTimer().cancel();
this.overdueClear(key, individual);
} else {
if (individual.get() == null) {
throw new Exception("数据已失效,不能再更新有效时间");
} else {
this.overdueClear(key, individual);
}
}
}
public void flushTime(String key, long effectiveTime) throws Exception {
CacheIndividual<?> individual = cacheMap.get(key);
if (individual != null) {
individual.setEffectiveTime(effectiveTime);
flushTime(key);
}
}
public void neverOverdue(String key) throws Exception {
CacheIndi
没有合适的资源?快使用搜索试试~ 我知道了~
SpringBoot轻量级缓存区
共11个文件
java:11个
需积分: 0 0 下载量 131 浏览量
2023-06-21
11:14:13
上传
评论
收藏 9KB ZIP 举报
温馨提示
将高频使用的数据,进行本地缓存。 适用于基于Spring服务,业务复杂,高频查库的人群。 1)缓存数据库基础数据,业务相关的基础数据,改动频率小,查询频率大,反复查库耗时,占用数据库连接池资源,将这部分数据进行本地缓存。 2)单JVM,高频入库查库资源,多线程,多任务共享资源,将其放入缓存区,无需每次改动或新增都入库,根据实际情况,尽量将资源放入缓存区,减少库操作。
资源推荐
资源详情
资源评论
收起资源包目录
cache.zip (11个子文件)
cache
CacheDistrict.java 9KB
ScheduleInvoke.java 235B
CacheDistrictUtils.java 7KB
TimeLineCache.java 3KB
AutoSortMap.java 3KB
CacheIndividual.java 2KB
CacheEnum.java 2KB
stream
StreamUtils.java 615B
ArrayStream.java 410B
MapStream.java 1KB
ListStream.java 2KB
共 11 条
- 1
资源评论
小河边...
- 粉丝: 0
- 资源: 1
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (单片机Proteus案例)DS18B20温度传感器protues仿真,包括avr16128 ds18b20两种单片机型号
- (单片机Proteus案例)AT89S51单片机用Proteus仿真案例约12例,包括计数器、动态数码显示、定时计数器等
- (单片机Proteus案例)AT89S51单片机用Proteus仿真案例约10例,包括广告灯、按键、计数器等
- (单片机Proteus案例)51单片机点阵protues仿真实现
- 最新运营商归属地数据库
- 111111111111111111111
- 汉诺塔python代码递归
- 汉诺塔python代码递归
- 汉诺塔python代码递归
- MySQL 8.0 实战教程从入门到项目实战.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功