日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

本地缓存之Guava简单使用

發布時間:2024/8/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 本地缓存之Guava简单使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 使用場景
  • Guava Cache 的優勢
  • Guava Cache使用
    • CacheLoader
    • Callable
    • 刪除
      • 主動刪除
      • 過期刪除
      • 基于容量刪除
      • 引用刪除
    • 高級用法
    • 并發設置
    • 更新鎖定
    • GuavaCache高級實戰之疑難問題
      • GuavaCache會oom(內存溢出)嗎
      • GuavaCache緩存到期就會立即清除嗎
      • GuavaCache如何找出最久未使用的數據

使用場景

隨著互聯網用戶越來越多,并發量、吞吐量越來越大

本地緩存的應用場景:

  • 對性能有非常高的要求
  • 不經常變化
  • 占用內存不大
  • 有訪問整個集合的需求
  • 數據允許不時時一致
    例如:拉勾網首頁,由于首頁經常被訪問,可以將職位信息:java開發、大數據開發等放在本地緩存中。
  • guava cache:高并發,不需要持久化
    currentHashMap:高并發
    Ehcached:持久化 二級緩存

    Guava Cache 的優勢

    緩存機制淘汰算法可參考博文:本地緩存之LRU FIFO實現

  • 緩存過期和淘汰機制:LRU
  • 并發處理能力:類似CurrentHashMap,是線程安全的,采用了分段鎖機制,將一個集合分成若干個人partiton ,每個Patrtiton一把鎖,master多分區,利用segement作分區
  • 更新鎖定:GuavaCache可以在CacheLoader的load方法中加以控制,對同一個key,只讓一個請求去讀源并回填緩存,其他請求阻塞等待。.
  • 集成數據源:而GuavaCache的get可以集成數據源,在從緩存中讀取不到時可以從數據源中讀取數據并回填緩
  • 監控緩存加載/命中情況
  • Guava Cache使用

    Cache創建:

    方法作用
    maximumSize容量
    expireAfterWrite緩存項在給定時間內沒有被寫訪問(創建或覆蓋),則回收
    recordStats緩存項在給定時間內沒有被讀/寫訪問,則回收
    removalListener移除監聽器
    weakKeys弱引用存儲鍵,當鍵沒有其它(強或軟)引用時,緩存項可以被垃圾回收
    weakValues使用弱引用存儲值。當值沒有其它(強或軟)引用時,緩存項可以被垃圾回收
    concurrencyLevel并發操作

    CacheLoader、Callable功能相同,都是在調用get方法時候,如果緩存不存在則指定數據源加載

    CacheLoader

    在創建緩存對象初始化時使用

    模擬數據源

    public static HashMap<Integer, Integer> sourceMap = new HashMap<>();static {for (int i = 0; i < 10; i++){sourceMap.put(i, i);}}

    使用demo

    public static void main(String[] args) throws ExecutionException {LoadingCache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(5).build(new CacheLoader<Object, Object>() {@Overridepublic Object load(Object o) throws Exception {return sourceMap.get(o);}});for (int i = 0; i < 10; i++){cache.get(i);}System.out.println(cache.size());System.out.println(cache.asMap());}

    Callable

    調用get方法時當緩存數據不存在時候從數據源加載數據

    使用demo:

    @Testpublic void call() throws ExecutionException {Cache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(5).build();Object value = cache.get(1, new Callable<Integer>() {@Overridepublic Integer call() throws Exception {return sourceMap.get(1);}});System.out.println(value);}

    刪除

    主動刪除

    @Testpublic void doDel() throws ExecutionException {LoadingCache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(5).expireAfterAccess(3, TimeUnit.SECONDS).build(new CacheLoader<Object, Object>() {@Overridepublic Object load(Object o) throws Exception {return sourceMap.get(o);}});initCache(cache);//主動刪除 key為1cache.invalidate(1);System.out.println("主動刪除");displayCache(cache);// 批量刪除cache.invalidateAll(Arrays.asList(1,2));System.out.println("批量刪除");displayCache(cache);}

    過期刪除

    expireAfterAccess:如果在一定時間內沒被訪問則數據過期

    @Testpublic void expireTimeDel() throws ExecutionException, InterruptedException {LoadingCache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(5).expireAfterAccess(3, TimeUnit.SECONDS).build(new CacheLoader<Object, Object>() {@Overridepublic Object load(Object o) throws Exception {return sourceMap.get(o);}});initCache(cache);Thread.sleep(1000);cache.getIfPresent(1);Thread.sleep(2000);displayCache(cache);}

    基于容量刪除

    @Testpublic void sizeDel() throws ExecutionException {LoadingCache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(1).build(new CacheLoader<Object, Object>() {@Overridepublic Object load(Object o) throws Exception {return sourceMap.get(o);}});Object v = cache.get(1);System.out.println(v);//自動刪除1Object v2 = cache.get(2);displayCache(cache);}

    引用刪除

    開啟weakValues功能,采用弱引用,對引用不了解的可以看看,我的文章

    @Testpublic void referenceDel(){Cache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(3).weakValues().build();cache.put("1",new Object());//強制垃圾回收System.gc();System.out.println(cache.getIfPresent("1"));}

    高級用法

    并發設置

    設置 concurrencyLevel 使得緩存支持并發的寫入和讀取

    Cache<Object, Object> cache = CacheBuilder.newBuilder().maximumSize(3).concurrencyLevel(Runtime.getRuntime().availableProcessors()).build();

    更新鎖定

    GuavaCache提供了一個refreshAfterWrite定時刷新數據的配置項,如果經過一定時間沒有更新或覆蓋,則會在下一次獲取該值的時候,會在后臺異步去刷新緩存

    刷新時只有一個請求回源取數據,其他請求會阻塞(block)在一個固定時間段,如果在該時間段內沒有獲得新值則返回舊值。

    @Testpublic void refresh() throws InterruptedException, ExecutionException {LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder().maximumSize(3).concurrencyLevel(Runtime.getRuntime().availableProcessors()).refreshAfterWrite(3, TimeUnit.SECONDS).build(new CacheLoader<Integer, Integer>() {@Overridepublic Integer load(Integer key) throws Exception {return sourceMap.get(key);}});cache.get(1);System.out.println("第一次取值: " + cache.getIfPresent(1));sourceMap.put(1, 10);Thread.sleep(5000);System.out.println("第二次取值: " + cache.getIfPresent(1));}

    應用場景:accesstoken token失效 從公網拿token 采用更新鎖定

    GuavaCache高級實戰之疑難問題

    GuavaCache會oom(內存溢出)嗎

    會,當我們設置緩存永不過期(或者很長),緩存的對象不限個數(或者很大)時,比如:

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

    解決方案:緩存時間設置相對小些,使用弱引用方式存儲對象

    GuavaCache緩存到期就會立即清除嗎

    不是的,GuavaCache是在每次進行緩存操作的時候,如get()或者put()的時候,判斷緩存是否過期。

    一個如果一個對象放入緩存以后,不在有任何緩存操作(包括對緩存其他key的操作),那么該緩存不
    會主動過期的。

    GuavaCache如何找出最久未使用的數據

    用accessQueue,這個隊列是按照LRU的順序放的緩存對象(ReferenceEntry)的,會把訪問過的對象放在隊列的最后。

    并且可以很方便的更新和刪除鏈表中的節點,因為每次訪問的時候都可能需要更新鏈表,放入到鏈表的尾部。

    這樣,每次從access中拿出的頭結點就是最久未使用的。

    對應的writeQueue用來保存最久未更新的緩存隊列,實現方式和accessQueue一樣。

    其他比較好的文章推薦:

    中文教程

    Guava總結好的博客

    總結

    以上是生活随笔為你收集整理的本地缓存之Guava简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。