Java本地缓存工具之LoadingCache的使用详解

目录
  • 前言
  • 环境依赖
  • 代码
  • 演示一下
  • 总结

前言

在工作总常常需要用到缓存,而redis往往是首选,但是短期的数据缓存一般我们还是会用到本地缓存。本文提供一个我在工作中用到的缓存工具,该工具代码为了演示做了一些调整。如果拿去使用的话,可以考虑做成注入Bean对象,看具体需求了。

环境依赖

先添加maven依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

代码

不废话,上代码了。

package ai.guiji.csdn.tools;

import cn.hutool.core.thread.ThreadUtil;
import com.google.common.cache.*;
import lombok.extern.slf4j.Slf4j;

import java.text.MessageFormat;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.LongStream;

/** @Author 剑客阿良_ALiang @Date 2021/12/30 17:57 @Description: 缓存工具 */
@Slf4j
public class CacheUtils {

  private static LoadingCache<Long, String> cache;

  /**
   * 初始化缓存方法
   *
   * @param totleCount 缓存池上限
   * @param overtime 超时时间
   * @param unit 时间单位
   * @param handleNotExist 处理不存在key方法
   * @param handleRemove 移除主键消费
   */
  private static void initCache(
      Integer totleCount,
      Integer overtime,
      TimeUnit unit,
      Function<Long, String> handleNotExist,
      Consumer<Long> handleRemove) {
    cache =
        CacheBuilder.newBuilder()
            // 缓存池大小
            .maximumSize(totleCount)
            // 设置时间对象没有被读/写访问则对象从内存中删除
            .expireAfterWrite(overtime, unit)
            // 移除监听器
            .removalListener(
                new RemovalListener<Long, String>() {
                  @Override
                  public void onRemoval(RemovalNotification<Long, String> rn) {
                    handleRemove.accept(rn.getKey());
                  }
                })
            .recordStats()
            .build(
                new CacheLoader<Long, String>() {
                  @Override
                  public String load(Long aLong) throws Exception {
                    return handleNotExist.apply(aLong);
                  }
                });
    log.info("初始化缓存");
  }

  /**
   * 存入缓存
   *
   * @param key 键
   * @param value 值
   */
  public static void put(Long key, String value) {
    try {
      log.info("缓存存入:[{}]-[{}]", key, value);
      cache.put(key, value);
    } catch (Exception exception) {
      log.error("存入缓存异常", exception);
    }
  }

  /**
   * 批量存入缓存
   *
   * @param map 映射
   */
  public static void putMap(Map<Long, String> map) {
    try {
      log.info("批量缓存存入:[{}]", map);
      cache.putAll(map);
    } catch (Exception exception) {
      log.error("批量存入缓存异常", exception);
    }
  }

  /**
   * 获取缓存
   *
   * @param key 键
   */
  public static String get(Long key) {
    try {
      return cache.get(key);
    } catch (Exception exception) {
      log.error("获取缓存异常", exception);
      return null;
    }
  }

  /**
   * 删除缓存
   *
   * @param key 键
   */
  public static void removeKey(Long key) {
    try {
      cache.invalidate(key);
    } catch (Exception exception) {
      log.error("删除缓存异常", exception);
    }
  }

  /**
   * 批量删除缓存
   *
   * @param keys 键
   */
  public static void removeAll(Iterable<Long> keys) {
    try {
      cache.invalidateAll(keys);
    } catch (Exception exception) {
      log.error("批量删除缓存异常", exception);
    }
  }

  /** 清理缓存 */
  public static void clear() {
    try {
      cache.invalidateAll();
    } catch (Exception exception) {
      log.error("清理缓存异常", exception);
    }
  }

  /**
   * 获取缓存大小
   *
   * @return 长度
   */
  public static long size() {
    return cache.size();
  }

  public static void main(String[] args) {
    initCache(
        Integer.MAX_VALUE,
        10,
        TimeUnit.SECONDS,
        k -> {
          log.info("缓存:[{}],不存在", k);
          return "";
        },
        x -> log.info("缓存:[{}],已经移除", x));
    System.out.println(size());
    LongStream.range(0, 10).forEach(a -> put(a, MessageFormat.format("tt-{0}", a)));
    System.out.println(cache.asMap());
    ThreadUtil.sleep(5000);
    LongStream.range(0, 10)
        .forEach(
            a -> {
              System.out.println(get(a));
              ThreadUtil.sleep(1000);
            });
    System.out.println(cache.asMap());
    ThreadUtil.sleep(10000);
    System.out.println(cache.asMap());
  }
}

代码说明

1、在初始化loadingCache的时候,可以添加缓存的最大数量、消逝时间、消逝或者移除监听事件、不存在键处理等等。在上面的代码中,我初始化缓存大小为Integer的最大值,写入10秒后消逝,如不存在key返回空字符串等等。

2、该类也提供了put、putAll、get、remove、removeAll、clear、size方法,可以对缓存进行存、取、删、清理、大小等操作。

3、main演示方法中,先往缓存存入10个数据,然后过5秒后每秒取一个数据,并且打印一下缓存中的全部内容。

4、补充一句LoadingCache是线程安全的哦。

演示一下

15:31:53.495 [main] INFO ai.guiji.csdn.tools.CacheUtils - 初始化缓存
0
15:31:53.502 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[0]-[tt-0]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[1]-[tt-1]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[2]-[tt-2]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[3]-[tt-3]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[4]-[tt-4]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[5]-[tt-5]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[6]-[tt-6]
15:31:53.508 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[7]-[tt-7]
15:31:53.509 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[8]-[tt-8]
15:31:53.509 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存存入:[9]-[tt-9]
{6=tt-6, 5=tt-5, 0=tt-0, 8=tt-8, 7=tt-7, 2=tt-2, 1=tt-1, 9=tt-9, 3=tt-3, 4=tt-4}
tt-0
tt-1
tt-2
tt-3
tt-4
15:32:03.572 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[5],已经移除
15:32:03.573 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[6],已经移除
15:32:03.573 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[5],不存在
15:32:04.581 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[6],不存在
15:32:05.589 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[0],已经移除
15:32:05.589 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[7],已经移除
15:32:05.589 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[8],已经移除
15:32:05.589 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[7],不存在
15:32:06.589 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[8],不存在
15:32:07.591 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[1],已经移除
15:32:07.591 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[2],已经移除
15:32:07.591 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[9],已经移除
15:32:07.591 [main] INFO ai.guiji.csdn.tools.CacheUtils - 缓存:[9],不存在
{6=, 5=, 8=, 7=, 9=}
{}
Process finished with exit code 0

可以看到,后面的5-9在内存中已经不存在对应的值了。

总结

本文提供的工具代码主要是为了演示,实际工作中可以按照自己的需求做调整。

到此这篇关于Java本地缓存工具之LoadingCache的使用详解的文章就介绍到这了,更多相关Java LoadingCache本地缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何基于LoadingCache实现Java本地缓存

    这篇文章主要介绍了如何基于LoadingCache实现Java本地缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 前言 Guava是Google开源出来的一套工具库.其中提供的cache模块非常方便,是一种与ConcurrentMap相似的缓存Map. 官方地址:https://github.com/google/guava/wiki/CachesExplained 开始构建 一. 添加依赖 <dependency> <groupI

  • 实现 Java 本地缓存的方法解析

    缓存,我相信大家对它一定不陌生,在项目中,缓存肯定是必不可少的.市面上有非常多的缓存工具,比如 Redis.Guava Cache 或者 EHcache.对于这些工具,我想大家肯定都非常熟悉,所以今天我们不聊它们,我们来聊一聊如何实现本地缓存.参考上面几种工具,要实现一个较好的本地缓存,平头哥认为要从以下三个方面开始. 1.存储集合的选择 实现本地缓存,存储容器肯定是 key/value 形式的数据结构,在 Java 中,也就是我们常用的 Map 集合.Map 中有 HashMap.Hashta

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

    这篇文章主要介绍了Java内存缓存工具Guava LoadingCache使用解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.Guava介绍 Guava是Google guava中的一个内存缓存模块,用于将数据缓存到JVM内存中.实际项目开发中经常将一些公共或者常用的数据缓存起来方便快速访问. Guava Cache是单个应用运行时的本地缓存.它不把数据存放到文件或外部服务器.如果不符合需求,可以选择Memcached.Redis等工具

  • Java本地缓存的实现代码

    使用场景 在 Java 应用中,对于访问频率高,更新少的数据,通常的方案是将这类数据加入缓存中.相对从数据库中读取来说,读缓存效率会有很大提升. 在集群环境下,常用的分布式缓存有 Redis . Memcached 等.但在某些业务场景上,可能不需要去搭建一套复杂的分布式缓存系统,在单机环境下,通常是会希望使用内部的缓存( LocalCache ). 实现 这里提供了两种 LocalCache 的实现,一种是基于 ConcurrentHashMap 实现基本本地缓存,另外一种是基于 Linked

  • Java本地缓存工具之LoadingCache的使用详解

    目录 前言 环境依赖 代码 演示一下 总结 前言 在工作总常常需要用到缓存,而redis往往是首选,但是短期的数据缓存一般我们还是会用到本地缓存.本文提供一个我在工作中用到的缓存工具,该工具代码为了演示做了一些调整.如果拿去使用的话,可以考虑做成注入Bean对象,看具体需求了. 环境依赖 先添加maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</arti

  • 微信小程序本地缓存数据增删改查实例详解

    微信小程序本地缓存数据增删改查实例详解 数据如: var user = { name: 'Lion', sex: 'guy' } CRUD: // 添加 wx.setStorageSync('user', user); // 查询 var developer = (wx.getStorageSync('user') || []); // 更改 developer.name = 'Lion01'; wx.setStorageSync('user', user); // 删除 wx.removeSt

  • Java多线程开发工具之CompletableFuture的应用详解

    做Java编程,难免会遇到多线程的开发,但是JDK8这个CompletableFuture类很多开发者目前还没听说过,但是这个类实在是太好用了,了解它的一些用法后相信你会对它爱不释手(呸渣男,咋对谁都爱不释手呢),好了我先简单举个列子,告诉你用它有多好.Single Dog拿一个Appointment来举个列子,如下: /** * 女神化完妆之后,还需要一小会选衣服,不过分吧. * 也就是说我们现在有2个异步任务,第一个是化妆,第二个是选衣服. * 选衣服要在化妆完成之后进行,这两个任务是串行

  • 缓存工具类ACache使用方法详解

    本文实例为大家分享了缓存工具类ACache的使用,供大家参考,具体内容如下 (1). ACache mCache = ACache.get(this); (2). String cacheData = mCache.getAsString("cache_data"); (3). if (!TextUtils.isEmpty(cacheData)) {                 解析.setAdapter.           } (4). 然后仍然请求网络,因为缓存的意义是为了在

  • 微信小程序如何修改本地缓存key中单个数据的详解

    最近在做教师评教系统,有一个'个人信息'页面中有个编辑修改邮箱的功能,本来想得很简单,结果进坑了,搞了好久才出来. 我想实现的效果是点击下图左侧邮箱,然后进入右侧页面,进行邮箱的修改,点击提交后跳转到左侧页面,同时邮箱也发生改变. 点击'我的'时,我让它从控制台打印出student缓存中传过来的数据,如下: {no: "1635050601", name: "张三", sex: "", email: "123@qq.com",

  • java树结构stream工具类的示例代码详解

    菜单实体类 package com.example.demo.entity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class Menu { /**

  • FasfDFS整合Java实现文件上传下载功能实例详解

    在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下. 今天使用Java代码实现文件的上传和下载.对此作者提供了Java API支持,下载fastdfs-client-java将源码添加到项目中.或者在Maven项目pom.xml文件中添加依赖 <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</arti

  • Java开发中synchronized的定义及用法详解

    概念 是利用锁的机制来实现同步的. 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问.互斥性我们也往往称为操作的原子性. 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致. 用法 修饰静态方法: //同步静态方法 public synchronized

随机推荐