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() // 寫入緩存后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() // 寫入緩存后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() // 寫入緩存后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í)行清除,而是在寫入或者讀取操作之后執(zhí)行少量維護(hù)工作,或者在寫入讀取很少的情況下,偶爾執(zhí)行清除操作。如果我們項(xiàng)目寫入或者讀取頻率很高,那么不用擔(dān)心。如果想入寫入和讀取操作頻率較低,那么我們可以通過(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ū)逐策略內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式
這篇文章主要介紹了Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Java實(shí)現(xiàn)輕松處理日期和時(shí)間的API小結(jié)
這篇文章主要為大家詳細(xì)介紹了Java中的日期和時(shí)間API,可以輕松處理日期和時(shí)間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03form-data與x-www-form-urlencoded的區(qū)別以及知識(shí)延伸
這篇文章主要給大家介紹了關(guān)于form-data與x-www-form-urlencoded的區(qū)別以及知識(shí)延伸,form-data和x-www-form-urlencoded都是HTTP請(qǐng)求中用于傳輸表單數(shù)據(jù)的編碼格式,需要的朋友可以參考下2023-11-11Java 負(fù)載均衡的 5 種算法實(shí)現(xiàn)原理
這篇文章主要介紹Java 負(fù)載均衡的 5 種算法實(shí)現(xiàn)原理,負(fù)載均衡能夠平均分配客戶請(qǐng)求到服 務(wù)器陣列,借此提供快速獲取重要數(shù)據(jù),解決大量并發(fā)訪問(wèn)服務(wù)問(wèn)題,這種集群技術(shù)可以用最少的投資獲得接近于大型主機(jī)的性能。下面就來(lái)看看文章的具體內(nèi)容吧2021-10-10Java訪問(wèn)Hadoop分布式文件系統(tǒng)HDFS的配置說(shuō)明
Hadoop的能提供高吞吐量的數(shù)據(jù)訪問(wèn),是集群式服務(wù)器的上的數(shù)據(jù)操作利器,這里就來(lái)為大家分享Java訪問(wèn)Hadoop分布式文件系統(tǒng)HDFS的配置說(shuō)明:2016-06-06