概述
Caffeine缓存注意事项-引用的都是同一地址的数据
Caffeine使用大家可以网上自行搜索,在这我就不在说明如何使用Caffeine了.
文章中心描述就是获取缓存中同一数据,如果对该数据某些字段参数赋值/改变会影响该缓存数据,全部代码在文末.
1: Caffeine中放入缓存数据(keyId1,keyId2,keyId3,keyId4)
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
String key = "keyId" + i;
int id = 10 + i;
int age = 10 + i;
String name = "test" + i;
//查询缓存,未命中赋值放入缓存(如:如果cache不存在,查询数据库,这里直接声明对象赋值)
CacheVo res = (CacheVo)cacheCaffeine.get(key, cacheVo -> {
CacheVo build = CacheVo.builder().id(id).age(age).name(name).build();
return build;
});
}
ArrayList<CacheVo> cacheVos = new ArrayList<>();
String key1 = "keyId1";
String key2 = "keyId2";
String key3 = "keyId3";
CacheVo ifPresent1 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent1.setRefId(1);
cacheVos.add(ifPresent1);
CacheVo ifPresent2 = (CacheVo)cacheCaffeine.getIfPresent(key2);
ifPresent2.setRefId(2);
cacheVos.add(ifPresent2);
CacheVo ifPresent3 = (CacheVo)cacheCaffeine.getIfPresent(key3);
ifPresent3.setRefId(3);
cacheVos.add(ifPresent3);
// 下面获取相同key 缓存(获取keyId1缓存)
CacheVo ifPresent4 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent4.setRefId(4);
cacheVos.add(ifPresent4);
CacheVo ifPresent5 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent5.setRefId(5);
cacheVos.add(ifPresent5);
}
2:debug查看集合中已放入的缓存对象数据,如下图,此时cacheVos集合中放入的是key为keyId1,keyId2,keyId3的数据(当前未插入相同key数据,so此时看似一切正常,注意集合前3个对象地址值和refId值)
3:cacheVos再次插入key为keyId1的数据,RefId赋值为4.如下图:细心的读者会发现cacheVos中index为0和3的数据是相同地址,且cacheVos中index为0的VO中refId值也变为4了.
此时再次debug获取key为keyId1的数据,读者会发现内存中的数据已改变.redId属性初始时并不是4
4:cacheVos再次插入key为keyId1的数据,RefId赋值为5.如下图:读者会发现cacheVos中index为0,3和4的数据是相同地址,且cacheVos中index为0的VO中refId值也变为5了.此时内存中的refId值也变为5
5:内存中key为keyId1的数据属性也已变化(多次都是对同一地址的VO对象改变refId属性值)
总结: Caffeine缓存中获取相同key的数据都是相同对象(地址相同),对该对象数据进行操作时会相应的改变内存缓存中的属性!!!大家注意使用避坑. 欢迎大家指点,第一次写博客,多多指教,有不足之处,请指出,谢谢.
所有test代码:
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.Builder;
import lombok.Data;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
/**
* @description: Caffeine缓存注意事项-引用的都是同一地址的数据
* @author: GL
* @create: 2021-11-03 16:39
**/
public class CaffeineTest {
/**
* maximumSize: 缓存的最大数量
* - maximumWeight: 缓存的最大权重
* - expireAfterAccess: 最后一次读或写操作后经过指定时间过期
* - expireAfterWrite: 最后一次写操作后经过指定时间过期
* - refreshAfterWrite: 创建缓存或者最近一次更新缓存后经过指定时间间隔,刷新缓存
* expireAfterWrite和expireAfterAccess同时存在时,以expireAfterWrite为准
*/
private static Cache<String, Object> cacheCaffeine = Caffeine.newBuilder()
.expireAfterWrite(24, TimeUnit.HOURS) //写入后隔段时间过期
// .refreshAfterWrite(60, TimeUnit.MINUTES) //写入后隔段时间刷新
// .expireAfterAccess(10, TimeUnit.HOURS) //访问后隔段时间过期
.maximumSize(1000)//最大条数
.build();//定义cache
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
String key = "keyId" + i;
int id = 10 + i;
int age = 10 + i;
String name = "test" + i;
//查询缓存,未命中赋值放入缓存(如:如果cache不存在,查询数据库,这里直接声明对象赋值)
CacheVo res = (CacheVo)cacheCaffeine.get(key, cacheVo -> {
CacheVo build = CacheVo.builder().id(id).age(age).name(name).build();
return build;
});
}
ArrayList<CacheVo> cacheVos = new ArrayList<>();
String key1 = "keyId1";
String key2 = "keyId2";
String key3 = "keyId3";
CacheVo ifPresent1 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent1.setRefId(1);
cacheVos.add(ifPresent1);
CacheVo ifPresent2 = (CacheVo)cacheCaffeine.getIfPresent(key2);
ifPresent2.setRefId(2);
cacheVos.add(ifPresent2);
CacheVo ifPresent3 = (CacheVo)cacheCaffeine.getIfPresent(key3);
ifPresent3.setRefId(3);
cacheVos.add(ifPresent3);
// 下面获取相同key 缓存(获取keyId1缓存)
CacheVo ifPresent4 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent4.setRefId(4);
cacheVos.add(ifPresent4);
CacheVo ifPresent5 = (CacheVo)cacheCaffeine.getIfPresent(key1);
ifPresent5.setRefId(5);
cacheVos.add(ifPresent5);
}
}
@Data
@Builder
class CacheVo{
private Integer id;
private Integer age;
private String name;
private Integer refId;
}
最后
以上就是欢喜蜗牛为你收集整理的Caffeine缓存注意事项(避坑)-引用的都是同一地址的数据的全部内容,希望文章能够帮你解决Caffeine缓存注意事项(避坑)-引用的都是同一地址的数据所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复