扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
小编给大家分享一下Java内存缓存工具Guava LoadingCache怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
创新互联公司是一家集网站建设,普安企业网站建设,普安品牌网站建设,网站定制,普安网站建设报价,网络营销,网络优化,普安网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。
一、Guava介绍
Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中。实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问。
Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果不符合需求,可以选择Memcached、redis等工具。
二、代码示例
1. POM引入
com.google.guava guava 28.1-jre
2. 封装工具类
package com.soyoung.ad.engine.util; import com.google.common.cache.*; import lombok.extern.slf4j.Slf4j; import java.util.Map; import java.util.concurrent.TimeUnit; /** * 功能描述 * * @author 马振全 2020/1/13 16:18 */ @Slf4j public class CacheManager { /** 缓存项最大数量 */ private static final long GUAVA_CACHE_SIZE = 100000; /** 缓存时间:天 */ private static final long GUAVA_CACHE_DAY = 10; /** 缓存操作对象 */ private static LoadingCacheGLOBAL_CACHE = null; static { try { GLOBAL_CACHE = loadCache(new CacheLoader () { @Override public String load(Long key) throws Exception { // 处理缓存键不存在缓存值时的处理逻辑 return ""; } }); } catch (Exception e) { log.error("初始化Guava Cache出错", e); } } /** * 全局缓存设置 * * 缓存项最大数量:100000 * 缓存有效时间(天):10 * * * @param cacheLoader * @return * @throws Exception */ private static LoadingCache loadCache(CacheLoader cacheLoader) throws Exception { LoadingCache cache = CacheBuilder.newBuilder() //缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项 .maximumSize(GUAVA_CACHE_SIZE) //设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护) .expireAfterAccess(GUAVA_CACHE_DAY, TimeUnit.DAYS) // 设置缓存在写入之后 设定时间 后失效 .expireAfterWrite(GUAVA_CACHE_DAY, TimeUnit.DAYS) //移除监听器,缓存项被移除时会触发 .removalListener(new RemovalListener () { @Override public void onRemoval(RemovalNotification rn) { //逻辑操作 } }) //开启Guava Cache的统计功能 .recordStats() .build(cacheLoader); return cache; } /** * 设置缓存值 * 注: 若已有该key值,则会先移除(会触发removalListener移除监听器),再添加 * * @param key * @param value */ public static void put(Long key, String value) { try { GLOBAL_CACHE.put(key, value); } catch (Exception e) { log.error("设置缓存值出错", e); } } /** * 批量设置缓存值 * * @param map */ public static void putAll(Map extends Long, ? extends String> map) { try { GLOBAL_CACHE.putAll(map); } catch (Exception e) { log.error("批量设置缓存值出错", e); } } /** * 获取缓存值 * 注:如果键不存在值,将调用CacheLoader的load方法加载新值到该键中 * * @param key * @return */ public static String get(Long key) { String token = ""; try { token = GLOBAL_CACHE.get(key); } catch (Exception e) { log.error("获取缓存值出错", e); } return token; } /** * 移除缓存 * * @param key */ public static void remove(Long key) { try { GLOBAL_CACHE.invalidate(key); } catch (Exception e) { log.error("移除缓存出错", e); } } /** * 批量移除缓存 * * @param keys */ public static void removeAll(Iterable keys) { try { GLOBAL_CACHE.invalidateAll(keys); } catch (Exception e) { log.error("批量移除缓存出错", e); } } /** * 清空所有缓存 */ public static void removeAll() { try { GLOBAL_CACHE.invalidateAll(); } catch (Exception e) { log.error("清空所有缓存出错", e); } } /** * 获取缓存项数量 * * @return */ public static long size() { long size = 0; try { size = GLOBAL_CACHE.size(); } catch (Exception e) { log.error("获取缓存项数量出错", e); } return size; } }
三、使用总结
1. 移除机制
guava做cache时候数据的移除分为被动移除和主动移除两种。
被动移除分为三种:
基于大小的移除:数量达到指定大小,会把不常用的键值移除
基于时间的移除:expireAfterAccess(long, TimeUnit) 根据某个键值对最后一次访问之后多少时间后移除
expireAfterWrite(long, TimeUnit) 根据某个键值对被创建或值被替换后多少时间移除
基于引用的移除:主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除
主动移除分为三种:1).单独移除:Cache.invalidate(key)
2).批量移除:Cache.invalidateAll(keys)
3).移除所有:Cache.invalidateAll()
如果配置了移除监听器RemovalListener,则在所有移除的动作时会同步执行该listener下的逻辑。
如需改成异步,使用:RemovalListeners.asynchronous(RemovalListener, Executor)
2. 遇到的问题
在put操作之前,如果已经有该键值,会先触发removalListener移除监听器,再添加
配置了expireAfterAccess和expireAfterWrite,但在指定时间后没有被移除。
解决方案:CacheBuilder构建的缓存不会在特定时间自动执行清理和回收工作,也不会在某个缓存项过期后马上清理,它不会启动一个线程来进行缓存维护,因为a)线程相对较重,b)某些环境限制线程的创建。它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做。当然,也可以创建自己的维护线程,以固定的时间间隔调用Cache.cleanUp()。
看完了这篇文章,相信你对“Java内存缓存工具Guava LoadingCache怎么用”有了一定的了解,如果想了解更多相关知识,欢迎关注创新互联行业资讯频道,感谢各位的阅读!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流