Java中的Caffeine加載與驅(qū)逐策略詳解
一、Caffiene 簡(jiǎn)介
Caffeine是基于Java 8的高性能緩存庫(kù),可提供接近最佳的命中率。
Caffeine與ConcurrentMap相應(yīng),但是不完全相同。最根本的區(qū)別是ConcurrentMap會(huì)保留所有添加到其中的元素,知道將其明確刪除為止. Cache另一方面,通常將A配置為自動(dòng)刪除元素,以限制其內(nèi)存占用量。在某些情況下,LoadingCache或AsyncLoadingCache可能很有用,即使它沒(méi)有刪除條目, 因?yàn)樗軌蜃詣?dòng)加載緩存信息。
二 、Caffeine四種加載策略
1.手動(dòng)加載緩存信息
Cache<String, Integer> cache = Caffeine.newBuilder()
// 寫(xiě)入緩存后30分鐘后過(guò)期
.expireAfterWrite(30, TimeUnit.MINUTES)
// 最大緩存數(shù)量1000
.maximumSize(1000)
.build();
String key = "1";
// 新增緩存
cache.put(key, 1);
cache.put("2", 2);
cache.put("3", 3);
// 從緩存中獲取數(shù)據(jù): 如果存在在返回"1"的值,如果不存在返回null
System.out.println(cache.getIfPresent(key));
// 緩存key不存在cache中, 則新增一條數(shù)據(jù)到cache中
String key1 = "4";
cache.get(key1, k -> 3);
System.out.println(cache.getIfPresent(key1));
// 從cache中移除緩存
cache.invalidate("1");2.LoadingCache
public void loadingCache() {
LoadingCache<String, Integer> loadingCache = Caffeine.newBuilder()
// 寫(xiě)入緩存后30分鐘后過(guò)期
.expireAfterWrite(30, TimeUnit.MINUTES)
// 最大緩存數(shù)量1000
.maximumSize(1000)
// build中的CacheLoader可以在初始化LoaddingCache時(shí),加載一部分?jǐn)?shù)據(jù)到內(nèi)存中,
// 此處就把key的hash值作為value
.build(this::getIntByKey);
Integer val = loadingCache.get("1", this::getIntByKey);
System.out.println(val);
// 批量獲取鍵值
Map<String, Integer> all = loadingCache.getAll(Arrays.asList("1", "2"));
System.out.println(JSON.toJSONString(all.values()));
}
public Integer getIntByKey(String key) {
return key.hashCode();
}3.異步手動(dòng)加載
public void sync() {
AsyncCache<String, Integer> asyncCache = Caffeine.newBuilder()
// 寫(xiě)入緩存后30分鐘后過(guò)期
.expireAfterWrite(30, TimeUnit.MINUTES)
// 最大緩存數(shù)量1000
.maximumSize(1000)
.buildAsync();
// 如果Key不存在, 則把key和value 加入到cache中, CompletableFuture提供了一個(gè)阻塞Cache, 直到異步完成
CompletableFuture<Integer> future = asyncCache.get("1", this::getIntByKey);
}
public Integer getIntByKey(String key) {
return key.hashCode();
}4.異步加載
public void syncLoadingCache() {
AsyncLoadingCache<String, Integer> async = Caffeine.newBuilder().buildAsync(new AsyncCacheLoader<>() {
@Override
public @NonNull CompletableFuture<Integer> asyncLoad(@NonNull String key, @NonNull Executor executor) {
return new CompletableFuture<>();
}
});
CompletableFuture<Integer> future = async.get("1");
CompletableFuture<Map<String, Integer>> all = async.getAll(Arrays.asList("1", "2"));
}三、CleanUp
由于Caffeine 不會(huì)再值過(guò)期后立即執(zhí)行清除,而是在寫(xiě)入或者讀取操作之后執(zhí)行少量維護(hù)工作,或者在寫(xiě)入讀取很少的情況下,偶爾執(zhí)行清除操作。如果我們項(xiàng)目寫(xiě)入或者讀取頻率很高,那么不用擔(dān)心。如果想入寫(xiě)入和讀取操作頻率較低,那么我們可以通過(guò)Cache.cleanUp() 加scheduler 去定時(shí)執(zhí)行清除操作。
Scheduler可以迅速刪除過(guò)期的元素,***Java 9 +***后的版本,可以通過(guò)Scheduler.systemScheduler(), 調(diào)用系統(tǒng) 線程,達(dá)到定期清除的目的
代碼實(shí)現(xiàn):
Cache<String, Integer> graphs = Caffeine.newBuilder()
// 設(shè)置一個(gè)定時(shí)器任務(wù)
.scheduler(Scheduler.systemScheduler())
// 添加一個(gè)移除元素監(jiān)聽(tīng)事件
.removalListener((k , v, cause) -> {
System.out.println(k);
System.out.println(v);
System.out.println(cause.wasEvicted());
})
.expireAfterWrite(3, TimeUnit.SECONDS)
.weakValues()
.build();
// 創(chuàng)建一個(gè)清理線程
Cleaner cleaner = Cleaner.create();
// 注冊(cè)一個(gè)對(duì)象,并在對(duì)象運(yùn)行時(shí)執(zhí)行一個(gè)cleanUp操作
cleaner.register("1", graphs::cleanUp);
graphs.put("1", 1);
graphs.put("2", 2);
graphs.put("3", 3);
Thread.sleep(5000);
graphs.put("3", 3);
System.out.println(graphs.getIfPresent("1"));
System.out.println(graphs.getIfPresent("2"));
System.out.println(graphs.getIfPresent("3"));到此這篇關(guān)于Java中的Caffeine加載與驅(qū)逐策略詳解的文章就介紹到這了,更多相關(guān)Caffeine加載與驅(qū)逐策略?xún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決使用mybatis取值,字段賦值錯(cuò)誤的問(wèn)題
這篇文章主要介紹了解決使用mybatis取值,字段賦值錯(cuò)誤的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
Java如何高效實(shí)現(xiàn)Word文檔對(duì)比
在項(xiàng)目協(xié)作、文檔審核或版本迭代的快節(jié)奏工作中,你是否曾為Word文檔的細(xì)微修改而抓狂,下面我們就來(lái)一起探討如何利用Java進(jìn)行Word文檔的自動(dòng)化比較吧2025-11-11
Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析
這篇文章介紹了Springboot項(xiàng)目出現(xiàn)java.lang.ArrayStoreException的異常分析,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
SpringBoot?中使用?Validation?校驗(yàn)參數(shù)的方法詳解
Validation?是用于檢查程序代碼中參數(shù)的有效性的框架,作為?Spring?框架中的一個(gè)參數(shù)校驗(yàn)工具,集成在?spring-context?包中,這篇文章主要介紹了SpringBoot?中使用?Validation?校驗(yàn)參數(shù),需要的朋友可以參考下2022-05-05
使用SpringMVC訪問(wèn)Controller接口返回400BadRequest
這篇文章主要介紹了使用SpringMVC訪問(wèn)Controller接口返回400BadRequest,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Spring的RedisTemplate的json反序列泛型丟失問(wèn)題解決
本文主要介紹了Spring RedisTemplate中使用JSON序列化時(shí)泛型信息丟失的問(wèn)題及其提出三種解決方案,可以根據(jù)性能需求選擇方案,下面就來(lái)具體了解一下2025-07-07
Java隊(duì)列篇之實(shí)現(xiàn)數(shù)組模擬隊(duì)列及可復(fù)用環(huán)形隊(duì)列詳解
像棧一樣,隊(duì)列(queue)也是一種線性表,它的特性是先進(jìn)先出,插入在一端,刪除在另一端。就像排隊(duì)一樣,剛來(lái)的人入隊(duì)(push)要排在隊(duì)尾(rear),每次出隊(duì)(pop)的都是隊(duì)首(front)的人2021-10-10
Java實(shí)現(xiàn)List分組的常見(jiàn)方法詳解
這篇文章主要為大家詳細(xì)介紹了使用Java實(shí)現(xiàn)List分組的幾個(gè)常見(jiàn)方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-12-12

