公众号后台回复“面试”,获取精品学习资料

扫描下方海报了解专栏详情

本文来源:阿飞的博客
《Java工程师面试突击(第3季)》重磅升级,由原来的70讲增至160讲,内容扩充一倍多,升级部分内容请参见文末
压力测试

简介
自动把数据加载到本地缓存中,并且可以配置异步; 基于数量剔除策略; 基于失效时间剔除策略,这个时间是从最后一次访问或者写入算起; 异步刷新; Key会被包装成Weak引用; Value会被包装成Weak或者Soft引用,从而能被GC掉,而不至于内存泄漏; 数据剔除提醒; 写入广播机制; 缓存访问可以统计;
使用
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>2.8.4</version></dependency>
然后构造Cache使用即可:
Cache<String, String> cache = Caffeine.newBuilder()数量上限.maximumSize(1024)/ 过期机制.expireAfterWrite(5, TimeUnit.MINUTES)// 弱引用key.weakKeys()// 弱引用value.weakValues()// 剔除监听.removalListener((RemovalListener<String, String>) (key, value, cause) ->System.out.println("key:" + key + ", value:" + value + ", 删除原因:" + cause.toString())).build();// 将数据放入本地缓存中cache.put("username", "afei");cache.put("password", "123456");// 从本地缓存中取出数据System.out.println(cache.getIfPresent("username"));System.out.println(cache.getIfPresent("password"));System.out.println(cache.get("blog", key -> {// 本地缓存没有的话,从数据库或者Redis中获取return getValue(key);}));
AsyncLoadingCache<String, String> cache = Caffeine.newBuilder()// 数量上限.maximumSize(2)// 失效时间.expireAfterWrite(5, TimeUnit.MINUTES).refreshAfterWrite(1, TimeUnit.MINUTES)// 异步加载机制.buildAsync(new CacheLoader<String, String>() {@Nullable@Overridepublic String load(@NonNull String key) throws Exception {return getValue(key);}});System.out.println(cache.get("username").get());System.out.println(cache.get("password").get(10, TimeUnit.MINUTES));System.out.println(cache.get("username").get(10, TimeUnit.MINUTES));System.out.println(cache.get("blog").get());
过期机制
expireAfterWrite:表示自从最后一次写入后多久就会过期; expireAfterAccess:表示自从最后一次访问(写入或者读取)后多久就会过期; expireAfter:自定义过期策略;
刷新机制
.build(new CacheLoader<String, String>() {@Overridepublic String load(String k) {// 这里我们就可以从数据库或者其他地方查询最新的数据return getValue(k);}});
剔除机制
「EXPLICIT」:调用方法(例如:cache.invalidate(key)、cache.invalidateAll)显示剔除数据; 「REPLACED」:不是真正被剔除,而是用户调用一些方法(例如:put(),putAll()等)盖了之前的值; 「COLLECTED」:表示缓存中的Key或者Value被垃圾回收掉了; 「EXPIRED」: expireAfterWrite/expireAfterAccess约定时间内没有任何访问导致被剔除; 「SIZE」:超过maximumSize限制的元素个数被剔除的原因;
GuavaCache和Caffeine差异
剔除算法方面,GuavaCache采用的是「LRU」算法,而Caffeine采用的是「Window TinyLFU」算法,这是两者之间最大,也是根本的区别。 立即失效方面,Guava会把立即失效 (例如:expireAfterAccess(0) and expireAfterWrite(0)) 转成设置最大Size为0。这就会导致剔除提醒的原因是SIZE而不是EXPIRED。Caffiene能正确识别这种剔除原因。 取代提醒方面,Guava只要数据被替换,不管什么原因,都会触发剔除监听器。而Caffiene在取代值和先前值的引用完全一样时不会触发监听器。 异步化方方面,Caffiene的很多工作都是交给线程池去做的(默认:ForkJoinPool.commonPool()),例如:剔除监听器,刷新机制,维护工作等。
内存占用对比

LRU P.K. W-TinyLFU




Guava迁移
// Guava's LoadingCache interfaceLoadingCache<Key, Graph> graphs = CaffeinatedGuava.build( Caffeine.newBuilder().maximumSize(10_000), new CacheLoader<Key, Graph>() { // Guava's CacheLoader @Override public Graph load(Key key) throws Exception { return createExpensiveGraph(key); } });
参考
END
《Java工程师面试突击第三季》加餐部分大纲:(注:1-66讲的大纲请扫描文末二维码,在课程详情页获取)



详细的课程内容,大家可以扫描下方二维码了解:





