Java内存缓存工具Guava LoadingCache使用解析

作者:森林木马 时间:2023-05-25 08:36:36 

这篇文章主要介绍了Java内存缓存工具Guava LoadingCache使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、Guava介绍

Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中。实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问。

Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果不符合需求,可以选择Memcached、Redis等工具。

二、代码示例

1. POM引入


<dependency>
 <groupId>com.google.guava</groupId>
 <artifactId>guava</artifactId>
 <version>28.1-jre</version>
</dependency>

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 LoadingCache<Long, String> GLOBAL_CACHE = null;

static {
   try {
     GLOBAL_CACHE = loadCache(new CacheLoader<Long, String>() {
       @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<Long, String> loadCache(CacheLoader<Long, String> cacheLoader) throws Exception {
   LoadingCache<Long, String> cache = CacheBuilder.newBuilder()
       //缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
       .maximumSize(GUAVA_CACHE_SIZE)
       //设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
       .expireAfterAccess(GUAVA_CACHE_DAY, TimeUnit.DAYS)
       // 设置缓存在写入之后 设定时间 后失效
       .expireAfterWrite(GUAVA_CACHE_DAY, TimeUnit.DAYS)
       //移除 * ,缓存项被移除时会触发
       .removalListener(new RemovalListener<Long, String>() {
         @Override
         public void onRemoval(RemovalNotification<Long, String> 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<Long> 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()。

来源:https://www.cnblogs.com/owenma/p/12191173.html

标签:Java,内存,缓存,Guava,Loading,Cache
0
投稿

猜你喜欢

  • 关于springcloud集成nacos遇到的问题

    2022-02-27 17:41:46
  • Android Internet应用实现获取天气预报的示例代码

    2023-09-26 04:13:22
  • VsCode使用EmmyLua插件调试Unity工程Lua代码的详细步骤

    2022-12-25 14:13:25
  • Android 自定义view和属性动画实现充电进度条效果

    2023-08-24 00:18:37
  • Java8新增的重复注解功能示例

    2022-09-06 22:49:58
  • C#使用CefSharp实现内嵌网页详解

    2022-04-12 15:02:00
  • SpringBoot实现WebSocket即时通讯的示例代码

    2022-06-14 19:59:36
  • 详解Spring框架注解扫描开启之配置细节

    2022-11-01 18:04:14
  • Java Grpc实例创建负载均衡详解

    2022-03-07 17:50:15
  • Android WebView 常见问题及处理方案

    2023-04-13 04:11:57
  • c#读写注册表示例分享

    2022-06-26 13:08:45
  • Android rom解包打包工具

    2023-09-01 21:49:10
  • Java DOM4J方式生成XML的方法

    2022-07-19 02:32:42
  • EL表达式的隐式对象_动力节点Java学院整理

    2022-10-13 06:04:01
  • Java String 字符串常量池解析

    2023-01-08 19:44:05
  • Java实现简单QQ聊天工具

    2023-11-25 05:54:52
  • Android实现图片转高斯模糊以及高斯模糊布局

    2023-10-20 16:10:23
  • C#实现创建标签PDF文件的示例代码

    2023-09-15 07:04:58
  • IDEA 设置显示内存的使用情况和内存回收的方法

    2023-10-08 15:51:25
  • Java swing读取txt文件实现学生考试系统

    2021-06-13 17:41:02
  • asp之家 软件编程 m.aspxhome.com