Java TimedCache 帶時(shí)間緩存工具類(lèi)詳解使用
簡(jiǎn)述
我們?cè)诠ぷ髦袝?huì)碰到需要使用帶過(guò)期時(shí)間的緩存場(chǎng)景。但是使用redis有太重了,畢竟緩存的數(shù)據(jù)很小,放在內(nèi)存夠夠的。hutools提供了TimedCache時(shí)間緩存工具,可以實(shí)現(xiàn)該場(chǎng)景。下面使用到該組件,并為了適配工作場(chǎng)景,對(duì)該工具類(lèi)做優(yōu)化升級(jí)。
Maven依賴(lài)
<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>
簡(jiǎn)單使用
不多說(shuō)了,上代碼。
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檢查一次過(guò)期 */
TIMED_CACHE.schedulePrune(5);
}
/**
* 存入鍵值對(duì),提供消逝時(shí)間
*
* @param key
* @param value
* @param timeout
*/
public static void put(String key, String value, Long timeout) {
/** 設(shè)置消逝時(shí)間 */
TIMED_CACHE.put(key, value, timeout);
}
/**
* 每次重新get一次緩存,均會(huì)重新刷新消逝時(shí)間
* @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次結(jié)果:" + get("haha"));
ThreadUtil.sleep(2000);
System.out.println("第2次結(jié)果:" + get("haha"));
ThreadUtil.sleep(5000);
System.out.println("第3次結(jié)果:" + get("haha"));
// 取消定時(shí)清理
TIMED_CACHE.cancelPruneSchedule();
}
}
首先我們看一下執(zhí)行的效果

說(shuō)明:
1、設(shè)置的超時(shí)時(shí)間為3000毫秒,所以第一次打印在2秒鐘,所以可以獲取到值。
2、因?yàn)榈谝淮未蛴≌{(diào)用了get方法,刷新了過(guò)期時(shí)間,所以依然可以獲取到值。
3、第三次打印在5秒后,所以已經(jīng)過(guò)期,無(wú)法獲取到值,打印null。
那么,需要知道是否緩存還在可以使用containsKey方法。如下:
put("haha", "1", 3000L);
ThreadUtil.sleep(2000);
if (TIMED_CACHE.containsKey("haha")) {
System.out.println("第1次結(jié)果:緩存存在");
}
// System.out.println("第1次結(jié)果:" + get("haha"));
ThreadUtil.sleep(2000);
System.out.println("第2次結(jié)果:" + get("haha"));
ThreadUtil.sleep(5000);
System.out.println("第3次結(jié)果:" + get("haha"));
// 取消定時(shí)清理
TIMED_CACHE.cancelPruneSchedule();
執(zhí)行結(jié)果如下:

工具優(yōu)化-監(jiān)聽(tīng)過(guò)期、增加回調(diào)
我們?cè)谑褂肨imedCache會(huì)發(fā)現(xiàn),一旦緩存過(guò)期我們并不能立馬知道,很多工作場(chǎng)景中需要對(duì)緩存做監(jiān)聽(tīng)回調(diào)。所以我升級(jí)了一下該工具類(lèi)。
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: 時(shí)間緩存工具 */
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);
/** 回調(diào)方法映射 */
private static ConcurrentHashMap<String, Consumer<String>> callbackMap;
/**
* 存入鍵值對(duì),添加過(guò)期時(shí)間,和消費(fèi)回調(diào)
*
* @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);
}
/**
* 刪除緩存和回調(diào)映射
*
* @param key
*/
public static void remove(String key) {
callbackMap.remove(key);
TIMED_CACHE.remove(key);
}
/**
* 添加監(jiān)聽(tīng)器
*
* @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"));
// 關(guān)閉監(jiān)聽(tīng)線程池
listeningExecutorService.shutdown();
}
}
執(zhí)行結(jié)果:

說(shuō)明:
1、可以看到監(jiān)聽(tīng)到緩存過(guò)期,并進(jìn)行了回調(diào)。
總結(jié)
具體的工具類(lèi)使用場(chǎng)景,因項(xiàng)目而異,大家看著來(lái)。
如果本文對(duì)你有幫助,請(qǐng)點(diǎn)個(gè)贊支持一下吧。

到此這篇關(guān)于Java TimedCache 帶時(shí)間緩存工具類(lèi)詳解使用的文章就介紹到這了,更多相關(guān)Java TimedCache內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Servlet和Filter之間的區(qū)別與聯(lián)系
這篇文章主要介紹了Servlet和Filter之間的區(qū)別與聯(lián)系的相關(guān)資料,需要的朋友可以參考下2016-05-05
Spring Boot 中的Servlet簡(jiǎn)單使用
在spring boot中添加自己的Servlet有兩種方法,代碼注冊(cè)Servlet和注解自動(dòng)注冊(cè)(Filter和Listener也是如此)。這篇文章主要介紹了Spring Boot 中的Servlet簡(jiǎn)單使用,需要的朋友可以參考下2017-04-04
Java實(shí)現(xiàn)Excel轉(zhuǎn)PDF的兩種方法詳解
使用具將Excel轉(zhuǎn)為PDF的方法有很多,在這里我給大家介紹兩種常用的方法:使用spire轉(zhuǎn)化PDF、使用jacob實(shí)現(xiàn)Excel轉(zhuǎn)PDF,分別應(yīng)對(duì)兩種不一樣的使用場(chǎng)景,需要的可以參考一下2022-01-01
6種Java創(chuàng)建對(duì)象的方式總結(jié)
在Java中,創(chuàng)建對(duì)象可以使用多種方式,本文將詳細(xì)介紹以下六種創(chuàng)建對(duì)象的方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-04-04
JavaWeb Struts文件上傳功能實(shí)現(xiàn)詳解
這篇文章主要為大家詳細(xì)介紹了JavaWeb Struts文件上傳功能實(shí)現(xiàn)過(guò)程,思路清晰,供大家參考,感興趣的小伙伴們可以參考一下2016-06-06
SpringBoot手動(dòng)開(kāi)啟事務(wù):DataSourceTransactionManager問(wèn)題
這篇文章主要介紹了SpringBoot手動(dòng)開(kāi)啟事務(wù):DataSourceTransactionManager問(wèn)題,具有很好的價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07

