最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java內(nèi)存緩存工具Guava LoadingCache使用解析

 更新時(shí)間:2020年01月16日 09:02:04   作者:森林木馬  
這篇文章主要介紹了Java內(nèi)存緩存工具Guava LoadingCache使用解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

這篇文章主要介紹了Java內(nèi)存緩存工具Guava LoadingCache使用解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

一、Guava介紹

Guava是Google guava中的一個(gè)內(nèi)存緩存模塊,用于將數(shù)據(jù)緩存到JVM內(nèi)存中。實(shí)際項(xiàng)目開發(fā)中經(jīng)常將一些公共或者常用的數(shù)據(jù)緩存起來方便快速訪問。

Guava Cache是單個(gè)應(yīng)用運(yùn)行時(shí)的本地緩存。它不把數(shù)據(jù)存放到文件或外部服務(wù)器。如果不符合需求,可以選擇Memcached、Redis等工具。

二、代碼示例

1. POM引入

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

2. 封裝工具類

package com.soyoung.ad.engine.util;
 
import com.google.common.cache.*;
import lombok.extern.slf4j.Slf4j;
 
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
/**
 * 功能描述
 *
 * @author 馬振全 2020/1/13 16:18
 */
@Slf4j
public class CacheManager {
 
  /** 緩存項(xiàng)最大數(shù)量 */
  private static final long GUAVA_CACHE_SIZE = 100000;
 
  /** 緩存時(shí)間:天 */
  private static final long GUAVA_CACHE_DAY = 10;
 
  /** 緩存操作對象 */
  private static LoadingCache<Long, String> GLOBAL_CACHE = null;
 
  static {
    try {
      GLOBAL_CACHE = loadCache(new CacheLoader<Long, String>() {
        @Override
        public String load(Long key) throws Exception {
          // 處理緩存鍵不存在緩存值時(shí)的處理邏輯
          return "";
        }
      });
    } catch (Exception e) {
      log.error("初始化Guava Cache出錯(cuò)", e);
    }
  }
 
  /**
   * 全局緩存設(shè)置
   *
   * 緩存項(xiàng)最大數(shù)量:100000
   * 緩存有效時(shí)間(天):10
   *
   *
   * @param cacheLoader
   * @return
   * @throws Exception
   */
  private static LoadingCache<Long, String> loadCache(CacheLoader<Long, String> cacheLoader) throws Exception {
    LoadingCache<Long, String> cache = CacheBuilder.newBuilder()
        //緩存池大小,在緩存項(xiàng)接近該大小時(shí), Guava開始回收舊的緩存項(xiàng)
        .maximumSize(GUAVA_CACHE_SIZE)
        //設(shè)置時(shí)間對象沒有被讀/寫訪問則對象從內(nèi)存中刪除(在另外的線程里面不定期維護(hù))
        .expireAfterAccess(GUAVA_CACHE_DAY, TimeUnit.DAYS)
        // 設(shè)置緩存在寫入之后 設(shè)定時(shí)間 后失效
        .expireAfterWrite(GUAVA_CACHE_DAY, TimeUnit.DAYS)
        //移除監(jiān)聽器,緩存項(xiàng)被移除時(shí)會(huì)觸發(fā)
        .removalListener(new RemovalListener<Long, String>() {
          @Override
          public void onRemoval(RemovalNotification<Long, String> rn) {
            //邏輯操作
          }
        })
        //開啟Guava Cache的統(tǒng)計(jì)功能
        .recordStats()
        .build(cacheLoader);
    return cache;
  }
 
  /**
   * 設(shè)置緩存值
   * 注: 若已有該key值,則會(huì)先移除(會(huì)觸發(fā)removalListener移除監(jiān)聽器),再添加
   *
   * @param key
   * @param value
   */
  public static void put(Long key, String value) {
    try {
      GLOBAL_CACHE.put(key, value);
    } catch (Exception e) {
      log.error("設(shè)置緩存值出錯(cuò)", e);
    }
  }
 
  /**
   * 批量設(shè)置緩存值
   *
   * @param map
   */
  public static void putAll(Map<? extends Long, ? extends String> map) {
    try {
      GLOBAL_CACHE.putAll(map);
    } catch (Exception e) {
      log.error("批量設(shè)置緩存值出錯(cuò)", e);
    }
  }
 
  /**
   * 獲取緩存值
   * 注:如果鍵不存在值,將調(diào)用CacheLoader的load方法加載新值到該鍵中
   *
   * @param key
   * @return
   */
  public static String get(Long key) {
    String token = "";
    try {
      token = GLOBAL_CACHE.get(key);
    } catch (Exception e) {
      log.error("獲取緩存值出錯(cuò)", e);
    }
    return token;
  }
 
  /**
   * 移除緩存
   *
   * @param key
   */
  public static void remove(Long key) {
    try {
      GLOBAL_CACHE.invalidate(key);
    } catch (Exception e) {
      log.error("移除緩存出錯(cuò)", e);
    }
  }
 
  /**
   * 批量移除緩存
   *
   * @param keys
   */
  public static void removeAll(Iterable<Long> keys) {
    try {
      GLOBAL_CACHE.invalidateAll(keys);
    } catch (Exception e) {
      log.error("批量移除緩存出錯(cuò)", e);
    }
  }
 
  /**
   * 清空所有緩存
   */
  public static void removeAll() {
    try {
      GLOBAL_CACHE.invalidateAll();
    } catch (Exception e) {
      log.error("清空所有緩存出錯(cuò)", e);
    }
  }
 
  /**
   * 獲取緩存項(xiàng)數(shù)量
   *
   * @return
   */
  public static long size() {
    long size = 0;
    try {
      size = GLOBAL_CACHE.size();
    } catch (Exception e) {
      log.error("獲取緩存項(xiàng)數(shù)量出錯(cuò)", e);
    }
    return size;
  }
}

三、使用總結(jié)

1. 移除機(jī)制

guava做cache時(shí)候數(shù)據(jù)的移除分為被動(dòng)移除和主動(dòng)移除兩種。

被動(dòng)移除分為三種:

基于大小的移除:數(shù)量達(dá)到指定大小,會(huì)把不常用的鍵值移除

基于時(shí)間的移除:expireAfterAccess(long, TimeUnit) 根據(jù)某個(gè)鍵值對最后一次訪問之后多少時(shí)間后移除
        expireAfterWrite(long, TimeUnit) 根據(jù)某個(gè)鍵值對被創(chuàng)建或值被替換后多少時(shí)間移除

基于引用的移除:主要是基于java的垃圾回收機(jī)制,根據(jù)鍵或者值的引用關(guān)系決定移除

主動(dòng)移除分為三種:1).單獨(dú)移除:Cache.invalidate(key)

         2).批量移除:Cache.invalidateAll(keys)

         3).移除所有:Cache.invalidateAll()

如果配置了移除監(jiān)聽器RemovalListener,則在所有移除的動(dòng)作時(shí)會(huì)同步執(zhí)行該listener下的邏輯。

如需改成異步,使用:RemovalListeners.asynchronous(RemovalListener, Executor)

2. 遇到的問題

在put操作之前,如果已經(jīng)有該鍵值,會(huì)先觸發(fā)removalListener移除監(jiān)聽器,再添加
配置了expireAfterAccess和expireAfterWrite,但在指定時(shí)間后沒有被移除。

解決方案:CacheBuilder構(gòu)建的緩存不會(huì)在特定時(shí)間自動(dòng)執(zhí)行清理和回收工作,也不會(huì)在某個(gè)緩存項(xiàng)過期后馬上清理,它不會(huì)啟動(dòng)一個(gè)線程來進(jìn)行緩存維護(hù),因?yàn)閍)線程相對較重,b)某些環(huán)境限制線程的創(chuàng)建。它會(huì)在寫操作時(shí)順帶做少量的維護(hù)工作,或者偶爾在讀操作時(shí)做。當(dāng)然,也可以創(chuàng)建自己的維護(hù)線程,以固定的時(shí)間間隔調(diào)用Cache.cleanUp()。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Java獲得多線程的返回結(jié)果方式(3種)

    淺談Java獲得多線程的返回結(jié)果方式(3種)

    這篇文章主要介紹了淺談Java獲得多線程的返回結(jié)果方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • 舉例說明Java設(shè)計(jì)模式編程中ISP接口隔離原則的使用

    舉例說明Java設(shè)計(jì)模式編程中ISP接口隔離原則的使用

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中ISP接口隔離原則的使用,接口隔離原則主張一個(gè)類對另外一個(gè)類的依賴性應(yīng)當(dāng)是建立在最小的接口上,需要的朋友可以參考下
    2016-02-02
  • Java使用CompletableFuture實(shí)現(xiàn)異步編程

    Java使用CompletableFuture實(shí)現(xiàn)異步編程

    在現(xiàn)代 Java 開發(fā)中,異步編程是一項(xiàng)重要技能,而 CompletableFuture 是從 Java 8 開始提供的一個(gè)功能強(qiáng)大的工具,用于簡化異步任務(wù)的編寫和組合,本文將詳細(xì)介紹 CompletableFuture 的基本使用和一些常見的應(yīng)用場景,需要的朋友可以參考下
    2025-01-01
  • Java IO流之字節(jié)輸入流的使用詳解

    Java IO流之字節(jié)輸入流的使用詳解

    這篇文章主要為大家詳細(xì)介紹了Java IO流中字節(jié)輸入流的使用,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定的幫助,需要的可以參考一下
    2022-08-08
  • Java編程數(shù)組中最大子矩陣簡便解法實(shí)現(xiàn)代碼

    Java編程數(shù)組中最大子矩陣簡便解法實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java編程數(shù)組中最大子矩陣簡便解法實(shí)現(xiàn)代碼,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • java線程池ExecutorService超時(shí)處理小結(jié)

    java線程池ExecutorService超時(shí)處理小結(jié)

    使用ExecutorService時(shí),設(shè)置子線程執(zhí)行超時(shí)是一個(gè)常見需求,本文就來詳細(xì)的介紹一下ExecutorService超時(shí)的三種方法,感興趣的可以了解一下
    2024-09-09
  • Java解析方法的調(diào)用關(guān)系示例詳解

    Java解析方法的調(diào)用關(guān)系示例詳解

    這篇文章主要介紹了Java解析方法的調(diào)用關(guān)系,方法在Java編程中用于封裝重復(fù)的代碼,提高代碼復(fù)用性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • Spring中的策略模式簡單實(shí)現(xiàn)與使用分析

    Spring中的策略模式簡單實(shí)現(xiàn)與使用分析

    這篇文章主要介紹了Spring中的策略模式簡單實(shí)現(xiàn)與使用分析,去初始化時(shí)除了?initMultipartResolver(上傳文件)沒有獲取?Properties?defaultStrategies;默認(rèn)策略,其他的八大件都會(huì)使用到策略模式,需要的朋友可以參考下
    2024-01-01
  • java的java.security.egd源碼解讀

    java的java.security.egd源碼解讀

    這篇文章主要為大家介紹了java的java.security.egd源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Mybatis 創(chuàng)建方法、全局配置教程詳解

    Mybatis 創(chuàng)建方法、全局配置教程詳解

    MyBatis是一個(gè)半自動(dòng)化的輕量級的持久化層框架。 MyBatis實(shí)際上是Ibatis3.0版本以后的持久化層框架,下面通過本文給大家分享Mybatis 創(chuàng)建方法、全局配置教程詳解,需要的朋友參考下吧
    2017-09-09

最新評論

洪湖市| 浦东新区| 灵寿县| 项城市| 哈密市| 商城县| 乐山市| 仙桃市| 拉孜县| 纳雍县| 始兴县| 仙居县| 中方县| 北碚区| 临夏县| 姜堰市| 新田县| 通渭县| 新巴尔虎右旗| 金昌市| 无棣县| 普安县| 阿勒泰市| 土默特右旗| 高青县| 乡宁县| 盘山县| 辰溪县| 阿图什市| 罗江县| 建德市| 喀什市| 监利县| 黄大仙区| 沙洋县| 房山区| 广州市| 鄄城县| 边坝县| 博兴县| 兴和县|