Java TimedCache 带时间缓存工具类详解使用

 更新时间:2021年10月27日 16:31:59   作者:剑客阿良_ALiang  
工具类是包含集合框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组、日期Date类、堆栈Stack类、向量Vector类等)。集合类、时间处理模式、日期工具等各类常用工具包,本文将介绍带时间缓存工具类

简述

我们在工作中会碰到需要使用带过期时间的缓存场景。但是使用redis有太重了,毕竟缓存的数据很小,放在内存够够的。hutools提供了TimedCache时间缓存工具,可以实现该场景。下面使用到该组件,并为了适配工作场景,对该工具类做优化升级。

Maven依赖

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.4.6</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>

简单使用

不多说了,上代码。

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.thread.ThreadUtil;
 
/** @Author huyi @Date 2021/10/12 17:00 @Description: */
public class TimedCacheUtils {
  private static final TimedCache<String, String> TIMED_CACHE = CacheUtil.newTimedCache(5000);
 
  static {
    /** 每5ms检查一次过期 */
    TIMED_CACHE.schedulePrune(5);
  }
 
  /**
   * 存入键值对,提供消逝时间
   *
   * @param key
   * @param value
   * @param timeout
   */
  public static void put(String key, String value, Long timeout) {
    /** 设置消逝时间 */
    TIMED_CACHE.put(key, value, timeout);
  }
 
  /**
   * 每次重新get一次缓存,均会重新刷新消逝时间
   * @param key
   * @return
   */
  public static String get(String key) {
    return TIMED_CACHE.get(key);
  }
 
  public static void main(String[] args) {
    put("haha", "1", 3000L);
    ThreadUtil.sleep(2000);
    //    if (TIMED_CACHE.containsKey("haha")) {
    //      System.out.println("aa");
    //    }
    System.out.println("第1次结果:" + get("haha"));
    ThreadUtil.sleep(2000);
    System.out.println("第2次结果:" + get("haha"));
    ThreadUtil.sleep(5000);
    System.out.println("第3次结果:" + get("haha"));
    // 取消定时清理
    TIMED_CACHE.cancelPruneSchedule();
  }
}

首先我们看一下执行的效果

说明:

1、设置的超时时间为3000毫秒,所以第一次打印在2秒钟,所以可以获取到值。

2、因为第一次打印调用了get方法,刷新了过期时间,所以依然可以获取到值。

3、第三次打印在5秒后,所以已经过期,无法获取到值,打印null。

那么,需要知道是否缓存还在可以使用containsKey方法。如下:

    put("haha", "1", 3000L);
    ThreadUtil.sleep(2000);
    if (TIMED_CACHE.containsKey("haha")) {
      System.out.println("第1次结果:缓存存在");
    }
//    System.out.println("第1次结果:" + get("haha"));
    ThreadUtil.sleep(2000);
    System.out.println("第2次结果:" + get("haha"));
    ThreadUtil.sleep(5000);
    System.out.println("第3次结果:" + get("haha"));
    // 取消定时清理
    TIMED_CACHE.cancelPruneSchedule();

执行结果如下:

工具优化-监听过期、增加回调

我们在使用TimedCache会发现,一旦缓存过期我们并不能立马知道,很多工作场景中需要对缓存做监听回调。所以我升级了一下该工具类。

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.thread.ThreadUtil;
import com.google.common.util.concurrent.*;
import org.checkerframework.checker.nullness.qual.Nullable;
 
import java.text.MessageFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
 
/** @Author huyi @Date 2021/10/12 10:57 @Description: 时间缓存工具 */
public class TimedCacheUtils {
  private static final TimedCache<String, String> TIMED_CACHE = CacheUtil.newTimedCache(5000);
  /** 线程池 */
  private static final ExecutorService executorService = Executors.newCachedThreadPool();
 
  private static final ListeningExecutorService listeningExecutorService =
      MoreExecutors.listeningDecorator(executorService);
  /** 回调方法映射 */
  private static ConcurrentHashMap<String, Consumer<String>> callbackMap;
 
  /**
   * 存入键值对,添加过期时间,和消费回调
   *
   * @param key
   * @param timeout
   * @param consumer
   */
  public static void put(String key, String value, Long timeout, Consumer<String> consumer) {
    TIMED_CACHE.put(key, value, timeout);
    addListen(key, consumer);
  }
 
  /**
   * 获取缓存值
   *
   * @param key
   * @return
   */
  public static String get(String key) {
    return TIMED_CACHE.get(key);
  }
 
  /**
   * 删除缓存和回调映射
   *
   * @param key
   */
  public static void remove(String key) {
    callbackMap.remove(key);
    TIMED_CACHE.remove(key);
  }
 
  /**
   * 添加监听器
   *
   * @param key
   * @param consumer
   */
  public static void addListen(String key, Consumer<String> consumer) {
    ListenableFuture<String> listenableFuture =
        listeningExecutorService.submit(
            () -> {
              while (TIMED_CACHE.containsKey(key)) {
                ThreadUtil.sleep(500);
              }
              return key;
            });
    Futures.addCallback(
        listenableFuture,
        new FutureCallback<String>() {
          @Override
          public void onSuccess(@Nullable String s) {
            consumer.accept(s);
          }
 
          @Override
          public void onFailure(Throwable throwable) {
            throwable.printStackTrace();
          }
        },
        listeningExecutorService);
  }
 
  public static void main(String[] args) {
    put("haha", "1", 3000L, x -> System.out.println(MessageFormat.format("[{0}] - 缓存消逝", x)));
    ThreadUtil.sleep(2000);
    System.out.println(get("haha"));
    ThreadUtil.sleep(2000);
    System.out.println(get("haha"));
    ThreadUtil.sleep(5000);
    System.out.println(get("haha"));
    // 关闭监听线程池
    listeningExecutorService.shutdown();
  }
}

执行结果:

说明:

1、可以看到监听到缓存过期,并进行了回调。

总结

具体的工具类使用场景,因项目而异,大家看着来。

如果本文对你有帮助,请点个赞支持一下吧。

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

相关文章

  • Servlet和Filter之间的区别与联系

    Servlet和Filter之间的区别与联系

    这篇文章主要介绍了Servlet和Filter之间的区别与联系的相关资料,需要的朋友可以参考下
    2016-05-05
  • java中线程池的关闭问题

    java中线程池的关闭问题

    这篇文章主要介绍了java中线程池的关闭问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • springboot分布式整合dubbo的方式

    springboot分布式整合dubbo的方式

    Dubbo是一款高性能、轻量级的开源Java RPC框架,本文通过实例代码给大家介绍springboot分布式整合dubbo的方式,感兴趣的朋友跟随小编一起看看吧
    2021-11-11
  • Spring Boot 中的Servlet简单使用

    Spring Boot 中的Servlet简单使用

    在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。这篇文章主要介绍了Spring Boot 中的Servlet简单使用,需要的朋友可以参考下
    2017-04-04
  • Java实现Excel转PDF的两种方法详解

    Java实现Excel转PDF的两种方法详解

    使用具将Excel转为PDF的方法有很多,在这里我给大家介绍两种常用的方法:使用spire转化PDF、使用jacob实现Excel转PDF,分别应对两种不一样的使用场景,需要的可以参考一下
    2022-01-01
  • 6种Java创建对象的方式总结

    6种Java创建对象的方式总结

    在Java中,创建对象可以使用多种方式,本文将详细介绍以下六种创建对象的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-04-04
  • 常用输入字节流InputStream介绍

    常用输入字节流InputStream介绍

    下面小编就为大家带来一篇常用输入字节流InputStream介绍。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • JavaWeb Struts文件上传功能实现详解

    JavaWeb Struts文件上传功能实现详解

    这篇文章主要为大家详细介绍了JavaWeb Struts文件上传功能实现过程,思路清晰,供大家参考,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • springboot redis分布式锁代码实例

    springboot redis分布式锁代码实例

    这篇文章主要介绍了springboot redis分布式锁代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • SpringBoot手动开启事务:DataSourceTransactionManager问题

    SpringBoot手动开启事务:DataSourceTransactionManager问题

    这篇文章主要介绍了SpringBoot手动开启事务:DataSourceTransactionManager问题,具有很好的价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07

最新评论