亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Guava Cache的使用簡介

 更新時間:2021年03月30日 09:23:00   作者:江湖段小二  
這篇文章主要介紹了Guava Cache的使用簡介,幫助大家更好的理解和學(xué)習(xí)使用Guava Cache,感興趣的朋友可以了解下

1 引入

說到緩存,可能大家最先想到的還是Redis。作為基于鍵值對的非關(guān)系型數(shù)據(jù)庫,Redis具有高性能、豐富的數(shù)據(jù)結(jié)構(gòu)、持久化、高可用、分布式等特性,使其在業(yè)內(nèi)得到了廣泛的認(rèn)可和使用。但是,使用Redis必然涉及到網(wǎng)絡(luò)連接,當(dāng)網(wǎng)絡(luò)連接不穩(wěn)定或網(wǎng)絡(luò)耗時嚴(yán)重時,必然會影響到我們的業(yè)務(wù)使用。如果我們想提高我們的業(yè)務(wù)性能,又減少對其他機(jī)器的依賴,那么,使用本地緩存會是一個不錯的選擇。

使用本地緩存時,大多時候我們會采用ConcurrentHashMap來實(shí)現(xiàn)。對于本地緩存的使用,現(xiàn)在有一些較為成熟的本地緩存工具,如ehcache、guava cache,以及Caffeine。當(dāng)需要對緩存進(jìn)行持久化操作時,可以考慮使用ehcache。如果沒有持久化操作,可以考慮使用guava cache或caffeine,caffeine是基于guava cache進(jìn)行的二次優(yōu)化,可根據(jù)自身業(yè)務(wù)需要選擇使用哪一種本地緩存工具,本文將針對在DRS系統(tǒng)中使用到的Guava Cache進(jìn)行講解。

在本次項(xiàng)目中,選擇的guava cache版本信息如下:

<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>30.1-jre</version>
</dependency>

2 Guava Cache介紹

Guava cache和ConcurrentHashMap很相似,都是采用的key-value鍵值對的方式進(jìn)行數(shù)據(jù)的存儲,都采用了分段加鎖的方式來提高多線程下的并發(fā)操作。不同的是,使用ConcurrentHashMap進(jìn)行緩存存儲時,會一直保留緩存數(shù)據(jù),直到系統(tǒng)重啟或顯示刪除緩存,而guava cache支持緩存過期時間的設(shè)置,可以進(jìn)行緩存清理操作。同時,guava cache還可以自動加載緩存,當(dāng)我們需要從數(shù)據(jù)庫中加載數(shù)據(jù)到緩存時,不需要每次在獲取緩存時判斷緩存是否存在,guava cache會按照我們設(shè)置的加載方式進(jìn)行數(shù)據(jù)的加載。除此之外,guava cache還可以進(jìn)行一些統(tǒng)計(jì)操作,如統(tǒng)計(jì)緩存的命中率、加載新值的平均時間等。正是由于Guava cache的這些特性,我們才選擇它應(yīng)用于DRS系統(tǒng)中。下面,來看看我們是如何使用Guava Cache進(jìn)行緩存管理操作的吧。

3 緩存的過期時間設(shè)置

Guava Cache支持三種過期設(shè)置,分別是基于容量的回收、定時回收,以及基于引用的回收。顯然,基于容量的回收和基于引用的回收跟緩存時間沒關(guān)系。當(dāng)我們需要設(shè)置緩存的緩存的過期時間時,使用的必然是定時回收的回收策略,那么,在guava cache中,支持兩種定時回收策略,分別是基于讀寫訪問的回收與基于寫訪問的回收,也就是緩存在設(shè)置的時間內(nèi)沒有被讀寫訪問或?qū)懺L問,緩存將會被回收,這種特性是可以滿足我們過期時間設(shè)置要求的。這兩種方法分別是: expireAfterAccess(long, TimeUnit):基于讀寫訪問的回收,緩存項(xiàng)在給定時間內(nèi)沒有被讀/寫訪問,則回收 expireAfterWrite(long, TimeUnit):基于寫訪問的回收,即緩存項(xiàng)在給定時間內(nèi)沒有被寫訪問,則回收 如下,給出了基于寫訪問的回收策略,過期時間設(shè)置的是3秒:

Cache<String, String> cache = CacheBuilder.newBuilder()
  .expireAfterWrite(3, TimeUnit.SECONDS)
  .build();

但是,在我們的項(xiàng)目中,需要針對不同的key設(shè)置不同的過期時間。而上面的示例中,只能滿足一種過期時間的設(shè)置,所有key的過期時間都是一樣的。為了滿足不同過期時間的需求,這里我們采用了一個兩級結(jié)構(gòu)的guava cache來實(shí)現(xiàn),如下所示:

private Cache<String, Cache<String, String>> cacheCache = CacheBuilder.newBuilder().build();
   
public void init() {
  Cache<String, String> cache1 = CacheBuilder.newBuilder()
    .expireAfterWrite(3, TimeUnit.SECONDS)
    .build();
  cache1.put("appName", "drs-server");
  Cache<String, String> cache2 = CacheBuilder.newBuilder()
    .expireAfterWrite(2, TimeUnit.SECONDS)
    .build();
  cache2.put("appName", "drs-ops");
  cacheCache.put("key1", cache1);
  cacheCache.put("key2", cache2);
}

在上面的示例中,還可以使用Map+guava cache的方式,也就是一個map里面套一個guava cache,定義如下:

Map<String, Cache<String, String>> cacheMap = new HashMap<String, Cache<String, String>>();

那為什么我們要使用一個兩級的cache結(jié)構(gòu)而不是Map+cache的方式呢?原因在于,當(dāng)讀取的數(shù)據(jù)在緩存中沒有時,我們是希望能夠自動去從數(shù)據(jù)庫加載的,所以使用兩級的cache結(jié)構(gòu)更合適。說到這里,就不得不提到guava cache的加載機(jī)制了。

4 緩存加載機(jī)制

guava cache有兩種方式加載,一種是在構(gòu)建緩存對象的時候,在build方法中設(shè)置緩存的加載方式(僅LocalCache對象可用);另一種是在獲取緩存對象的時候,通過實(shí)現(xiàn)Callable接口方法的方式設(shè)置加載方式。 采用如下的方式構(gòu)建緩存對象:

LoadingCache<String, String> cache = CacheBuilder.newBuilder()
  .build(new CacheLoader<String, String>() {
    @Override
    public String load(String s) throws Exception {
      return "load: " + UUID.randomUUID().toString().substring(1, 6);
    }
  });

通過上述方式構(gòu)建完LocalCache的緩存對象,當(dāng)調(diào)用get(K key)方法獲取緩存時,如果指定的key對應(yīng)的緩存值不存在,則會從load的方法中加載對象。但是,如果使用的是getIfPresent方法,則不會從執(zhí)行l(wèi)oad方法中加載緩存值,而是返回null值。當(dāng)時用get(K key, Callable call) 獲取緩存時,如果對應(yīng)的緩存值不存在,則會從實(shí)現(xiàn)的Callable接口方法中來加載緩存。完整的示例代碼如下所示:

public static void main(String[] args) throws Exception{
  LoadingCache<String, String> cache = CacheBuilder.newBuilder()
    .build(new CacheLoader<String, String>() {
      @Override
      public String load(String s) throws Exception {
        return "load: " + UUID.randomUUID().toString().substring(1, 6);
      }
    });
   
  System.out.println(cache.getIfPresent("appName1"));
  System.out.println(cache.get("appName2"));
 
  String loadValue = cache.get("appName3", new Callable<String>() {
    @Override
    public String call() throws Exception {
      return "call: " + UUID.randomUUID().toString().substring(1, 6);
    }
  });
  System.out.println(loadValue);
}

測試結(jié)果如下:

5 緩存清理

既然我們給緩存設(shè)置了過期時間,那么,緩存過期時間到了后,又是怎么來清理的呢?實(shí)際上,過期后的緩存并不會“自動”進(jìn)行清理,而是在下一次進(jìn)行讀訪問或是寫訪問的時候,通過判斷當(dāng)前時間與緩存加載進(jìn)來時的時間進(jìn)行比較,如果時間差大于給定的過期時間,則會清理緩存。如果設(shè)置了緩存的加載方式,則會重新加載緩存值,緩存的加載時間也會更新。通過代碼調(diào)試可以發(fā)現(xiàn),緩存清理是在get方法里實(shí)現(xiàn)的,用到的以下幾個方法:

get(Object key, int hash); // 獲取緩存值
getLiveEntry(Object key, int hash, long now); // 獲取存活的對象
isExpired(ReferenceEntry<K, V> entry, long now); // 判斷是否過期
expireEntries(long now); // 清理緩存

其中,判斷是否過期的邏輯如下:

如果緩存已過期,則返回true,然后執(zhí)行緩存清理刪除操作,如下所示:

除此之外,guava cache還支持緩存的一些統(tǒng)計(jì)工作,如統(tǒng)計(jì)緩存命中率、加載新值的平均時間、緩存項(xiàng)被回收的總數(shù)等,還有緩存中斷操作和刷新操作,由于本次項(xiàng)目中沒有使用到這些特性,沒有進(jìn)行深入的了解,感興趣的同學(xué)如有使用到,可以去官方網(wǎng)站進(jìn)行深入了解,詳見ifeve.com/google-guav…

以上就是Guava Cache的使用簡介的詳細(xì)內(nèi)容,更多關(guān)于Guava Cache的使用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java取兩個字符串的最大交集

    java取兩個字符串的最大交集

    這篇文章主要介紹了java取兩個字符串的最大交集的方法,涉及Java對字符串操作的技巧,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-10-10
  • 利用openoffice+jodconverter-code-3.0-bate4實(shí)現(xiàn)ppt轉(zhuǎn)圖片

    利用openoffice+jodconverter-code-3.0-bate4實(shí)現(xiàn)ppt轉(zhuǎn)圖片

    這篇文章主要為大家詳細(xì)介紹了利用openoffice+jodconverter-code-3.0-bate4實(shí)現(xiàn)ppt轉(zhuǎn)圖片,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • 淺談Mybatis+mysql 存儲Date類型的坑

    淺談Mybatis+mysql 存儲Date類型的坑

    這篇文章主要介紹了淺談Mybatis+mysql 存儲Date類型的坑,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • Java中實(shí)體與Map之間的相互轉(zhuǎn)換代碼示例

    Java中實(shí)體與Map之間的相互轉(zhuǎn)換代碼示例

    生活中經(jīng)常用到map數(shù)據(jù)與實(shí)體類的轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于Java中實(shí)體與Map之間相互轉(zhuǎn)換的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • RabbitMQ消息隊(duì)列的目錄結(jié)構(gòu)

    RabbitMQ消息隊(duì)列的目錄結(jié)構(gòu)

    這篇文章主要介紹了RabbitMQ消息隊(duì)列的目錄結(jié)構(gòu),RabbitMQ?屬于消息中間件,主要用于組件之間的解耦,消息的發(fā)送者無需知道消息使用者的存在,反之亦然,那么用了那么久RabbitMQ,其目錄結(jié)構(gòu)是怎樣的呢,讓我們一起來看一下吧
    2023-08-08
  • mybatis?example如何自動生成代碼?排序語句

    mybatis?example如何自動生成代碼?排序語句

    這篇文章主要介紹了mybatis?example如何自動生成代碼?排序語句,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Springbean的幾種注入方式都了解嗎

    Springbean的幾種注入方式都了解嗎

    這篇文章主要介紹了Springbean的幾種注入方式都了解嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Java語言中4種內(nèi)部類的超詳細(xì)講解

    Java語言中4種內(nèi)部類的超詳細(xì)講解

    這篇文章主要給大家介紹了關(guān)于Java語言中4種內(nèi)部類的超詳細(xì)講解,內(nèi)部類可以分為:實(shí)例內(nèi)部類、靜態(tài)內(nèi)部類和成員內(nèi)部類,每種內(nèi)部類都有它特定的一些特點(diǎn),文中介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Mybatis控制臺打印Sql語句的實(shí)現(xiàn)代碼

    Mybatis控制臺打印Sql語句的實(shí)現(xiàn)代碼

    MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架,下面給大家介紹Mybatis控制臺打印Sql語句的實(shí)現(xiàn)代碼,非常不錯,感興趣的朋友一起看下吧
    2016-07-07
  • springboot+springmvc+mybatis項(xiàng)目整合

    springboot+springmvc+mybatis項(xiàng)目整合

    這篇文章主要為大家詳細(xì)介紹了springboot+springmvc+mybatis項(xiàng)目的整合,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04

最新評論