1. 程式人生 > >二分鐘快速掌握Caffeine 三種填充策略:手動、同步和非同步

二分鐘快速掌握Caffeine 三種填充策略:手動、同步和非同步

 一、簡介

Caffeine — 一個高效能的 Java 快取庫。快取和 Map 之間的一個根本區別在於快取可以回收儲存的 item。回收策略為在指定時間刪除哪些物件。此策略直接影響快取的命中率 — 快取庫的一個重要特徵。Caffeine 因使用 Window TinyLfu 回收策略,提供了一個近乎最佳的命中率。

二、Caffeine 為我們提供了三種填充策略:手動、同步和非同步

1、手動載入(Manual)

Cache<String, Object> manualCache = Caffeine.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .maximumSize(10_000)
        .build();

String key = "name1";
// 根據key查詢一個快取,如果沒有返回NULL
graph = manualCache.getIfPresent(key);
// 根據Key查詢一個快取,如果沒有呼叫createExpensiveGraph方法,並將返回值儲存到快取。
// 如果該方法返回Null則manualCache.get返回null,如果該方法丟擲異常則manualCache.get丟擲異常
graph = manualCache.get(key, k -> createExpensiveGraph(k));
// 將一個值放入快取,如果以前有值就覆蓋以前的值
manualCache.put(key, graph);
// 刪除一個快取
manualCache.invalidate(key);

ConcurrentMap<String, Object> map = manualCache.asMap();
cache.invalidate(key);

Cache介面允許顯式的去控制快取的檢索,更新和刪除。
我們可以通過cache.getIfPresent(key) 方法來獲取一個key的值,通過cache.put(key, value)方法顯示的將數控放入快取,
但是這樣子會覆蓋緩原來key的資料。更加建議使用cache.get(key,k - > value) 的方式,get 方法將一個引數為 key 的
 Function (createExpensiveGraph) 作為引數傳入。如果快取中不存在該鍵,則呼叫這個 Function 函式,並將返回值作為
該快取的值插入快取中。get 方法是以阻塞方式執行呼叫,即使多個執行緒同時請求該值也只會呼叫一次Function方法。
這樣可以避免與其他執行緒的寫入競爭,這也是為什麼使用 get 優於 getIfPresent 的原因。

注意:如果呼叫該方法返回NULL(如上面的 createExpensiveGraph 方法),則cache.get返回null,如果呼叫該方法丟擲異常,則get方法也會丟擲異常。可以使用Cache.asMap() 方法獲取ConcurrentMap進而對快取進行一些更改。

2、同步載入(Loading)

LoadingCache<String, Object> loadingCache = Caffeine.newBuilder()
        .maximumSize(10_000)
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .build(key -> createExpensiveGraph(key));
    
String key = "name1";
// 採用同步方式去獲取一個快取和上面的手動方式是一個原理。在build Cache的時候會提供一個createExpensiveGraph函式。
// 查詢並在缺失的情況下使用同步的方式來構建一個快取
Object graph = loadingCache.get(key);

// 獲取組key的值返回一個Map
List<String> keys = new ArrayList<>();
keys.add(key);
Map<String, Object> graphs = loadingCache.getAll(keys);

LoadingCache是使用CacheLoader來構建的快取的值。批量查詢可以使用getAll方法。預設情況下,getAll將會對快取中沒有值的key分別呼叫CacheLoader.load方法來構建快取的值。我們可以重寫CacheLoader.loadAll方法來提高getAll的效率。

注意:您可以編寫一個CacheLoader.loadAll來實現為特別請求的key載入值。
例如,如果計算某個組中的任何鍵的值將為該組中的所有鍵提供值,則loadAll可能會同時載入該組的其餘部分。

3、非同步載入(Asynchronously Loading)

AsyncLoadingCache<String, Object> asyncLoadingCache = Caffeine.newBuilder()
            .maximumSize(10_000)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            // Either: Build with a synchronous computation that is wrapped as asynchronous
            .buildAsync(key -> createExpensiveGraph(key));
            // Or: Build with a asynchronous computation that returns a future
            // .buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));

 String key = "name1";

// 查詢並在缺失的情況下使用非同步的方式來構建快取
CompletableFuture<Object> graph = asyncLoadingCache.get(key);
// 查詢一組快取並在缺失的情況下使用非同步的方式來構建快取
List<String> keys = new ArrayList<>();
keys.add(key);
CompletableFuture<Map<String, Object>> graphs = asyncLoadingCache.getAll(keys);
// 非同步轉同步
loadingCache = asyncLoadingCache.synchronous();

AsyncLoadingCache是繼承自LoadingCache類的,非同步載入使用Executor去呼叫方法並返回一個CompletableFuture。非同步載入快取使用
了響應式程式設計模型。如果要以同步方式呼叫時,應提供CacheLoader。要以非同步表示時,應該提供一個AsyncCacheLoader,並返回一個CompletableFuture。synchronous()這個方法返回了一個LoadingCacheView檢視,LoadingCacheView也繼承自LoadingCache。呼叫該方法後就相當於你將一個非同步載入的快取AsyncLoadingCache轉換成了一個同步載入的快取LoadingCache。

預設使用ForkJoinPool.commonPool()來執行非同步執行緒,但是我們可以通過Caffeine.executor(Executor) 方法來替換執行緒池。

相關推薦

分鐘快速掌握Caffeine 填充策略手動同步非同步

 一、簡介 Caffeine — 一個高效能的 Java 快取庫。快取和 Map 之間的一個根本區別在於快取可以回收儲存的 item。回收策略為在指定時間刪除哪些物件。此策略直接影響快取的命中率 — 快取庫的一個重要特徵。Caffeine 因使用 Window TinyLf

處理大數據流常用的Apache框架StormSparkSamza。(主要介紹Storm)

領導 hdf 客戶端 orm 至少 per yar 持續性 apache 處理實時的大數據流最常用的就是分布式計算系統,下面分別介紹Apache中處理大數據流的三大框架: Apache Storm 這是一個分布式實時大數據處理系統。Storm設計用於在容錯和

適配器BaseAdapterSimpleAdapterArrayAdapter

混合體 ack xtend ont 模擬 tro 其中 emc 集合 一、寫在前面:   本次我們來講解一下Android應用中三個適配器:BaseAdapter、SimpleAdapter和ArrayAdapter。其中常見的是BaseAdapter,也是個人推薦使用的適

Java程式碼複用的常用方式繼承組合代理

複用程式碼是Java眾多引人注目的功能之一。這句話很通順,沒什麼問題,但問題在於很多人並不清楚“複用”是什麼。就好像我說“沉默王二是一個不止會寫程式碼的程式設計師”,唉,沉默王二是誰? 如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加

Java代碼復用的常用方式繼承組合代理

是個 繼續 不想 完成 extend 工作 代碼復用 輕松 例如 復用代碼是Java眾多引人註目的功能之一。這句話很通順,沒什麽問題,但問題在於很多人並不清楚“復用”是什麽。就好像我說“沈默王二是一個不止會寫代碼的程序員”,唉,沈默王二是誰? 我們需要來給“復用”下一個定義

雲計算的服務模式IaaS,PaaSSaaS

雲服務 互聯網 src 部分 stand googl 而且 vnc rackspace   雲服務”現在已經成了一個家喻戶曉的詞了。如果你不知道PaaS, IaaS 和SaaS的區別,那麽也沒啥,因為很多人確實不知道。  “雲”其實是互聯網的一個隱喻,“雲計算”其實就是使用

Web Service平臺有元素構成SOAPWSDLUDDI。區別聯絡

Web Service平臺有三種元素構成:SOAP、WSDL、UDDI。一個消費者可以在UDDI登錄檔查詢服務,取得服務的WSDL描述,然後通過SOAP來呼叫服務。SOAP、WSDL、UDDI的區別如下:1. SOAP(Simple Object Access Protocol,簡單物件訪問協議)① SOAP

Autofac學習之生命週期InstancePerLifetimeScopeSingleInstanceInstancePerDependency

InstancePerLifetimeScope:同一個Lifetime生成的物件是同一個例項 SingleInstance:單例模式,每次呼叫,都會使用同一個例項化的物件;每次都用同一個物件; InstancePerDependency:預設模式,每次呼叫,都會重新

Java web的打包方式jarwarear

  以最終客戶的角度來看,JAR檔案就是一種封裝,他們不需要知道jar檔案中有多少個.class檔案,每個檔案中的功能與作用,同樣可以得到他們希望的結果。除jar以外對於J2EE來說還有war和ear。區別見下表: JAR WAR EAR 英文 Java Ar

雲端計算的服務模式IaaS,PaaSSaaS

原文連結:http://www.cnblogs.com/beanmoon/archive/2012/12/10/2811547.html 雲服務”現在已經快成了一個家喻戶曉的詞了。如果你不知道PaaS, IaaS 和SaaS的區別,那麼也沒啥,因為很多人確實不知道。  “雲”

Hibernate的連線池設定C3P0dbcpProxool

<!-- JDBC驅動程式 --> <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property><property name="connec

資料庫中的連結策略 hash joinmerge join nested loop

1) 巢狀連線(nested loop join) Nested loops 工作方式是迴圈從一張表中讀取資料(驅動表outer table),然後訪問另一張表(被查詢表 inner table,通常有索引)。驅動表中的每一行與inner表中的相應記錄J

阿里雲大資料次技術突圍GreenplumHadoop飛天

對於企業來說,到底什麼是雲端計算?相信很多企業都有這樣的困惑,讓我們一起回到這個原始的起點探討究竟什麼是雲端計算?雲端計算對於企業而言到底意味什麼? 雲端計算的三條發展路徑及三種落地形態 當回到最初的起點再審視雲端計算的發展路徑,可以發現,經過十餘年的發

阻塞非阻塞同步非同步 IO模型

阻塞和非阻塞,同步和非同步1 例子故事:老王燒開水。出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。老王想了想,有好幾種等待方式1.老王用水壺煮水,並且站在那裡,不管水開沒開,每隔一定時間看看水開了沒。-同步阻塞老王想了想,這種方法不夠聰明。2.老王還

簡述併發程式設計分為個核心問題分工同步互斥。

    總的來說,併發程式設計可以總結為三個核心問題:分工、同步、互斥。  

【Java併發基礎】併發程式設計領域的個問題分工同步互斥

前言 可以將Java併發程式設計抽象為三個核心問題:分工、同步和互斥。 這三個問題的產生源自對效能的需求。最初時,為提高計算機的效率,當IO在等待時不讓CPU空閒,於是就出現了分時作業系統也就出現了併發。後來,多核CPU出現,不同的任務可以同時獨立執行,於是就出現了並行【分工】。有了分工後,效率得到了很大的提

方式求 輸入一個整數,輸出該數進制表示中1的個數。其中負數用補碼表示

情況 temp 進制數 二進制表示 pac print 類型 solution 方式 package com.example; public class Solution { /* * 轉化成2進制數計算 */ public int NumberOf1(int n) {

叉樹求第遍歷序列

btree har dex logs 由於 bsp int tin 推理 // 樹的結點的結構: struct TreeNode{ TreeNode* LChild; TreeNode* RChild; char data; };

Zookeeper-5分鐘快速掌握分布式應用程序協調服

form info class isa client 查看服務是否啟動 ats clean 進入 一、Zookeeper 安裝 1.zookeeper支持brew安裝。 ? ~ brew info zookeeper zookeeper: stable 3.4.10 (

分鐘快速掌握RPC原理及實現

隨著公司規模的不斷擴大,以及業務量的激增,單體應用逐步演化為服務/微服務的架構模式, 服務之間的呼叫大多采用rpc的方式呼叫,或者訊息佇列的方式進行解耦。幾乎每個大廠都會建立自己的rpc框架,或者基於知名的rpc框架進行改造因此今天我們來講講rpc吧。   ​RPC概述 RPC(