JAVA memory caching tool guava loadingcache usage parsing

This article mainly introduces the usage analysis of JAVA memory cache tool guava loadingcache. It is introduced in great detail through the example code, which has certain reference value for everyone's study or work. Friends in need can refer to it

1、 Introduction to guava

Guava is a memory cache module in Google guava, which is used to cache data into JVM memory. In the actual project development, some public or common data are often cached for quick access.

Guava cache is the local cache when a single application runs. It does not store data to files or external servers. If it does not meet the requirements, you can select tools such as memcached and redis.

2、 Code example

1. POM introduction

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

2. Packaging tools

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 {

  /** 缓存项最大数量 */
  private static final long GUAVA_CACHE_SIZE = 100000;

  /** 缓存时间:天 */
  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 {
          // 处理缓存键不存在缓存值时的处理逻辑
          return "";
        }
      });
    } catch (Exception e) {
      log.error("初始化Guava Cache出错",e);
    }
  }

  /**
   * 全局缓存设置
   *
   * 缓存项最大数量:100000
   * 缓存有效时间(天):10
   *
   *
   * @param cacheLoader
   * @return
   * @throws Exception
   */
  private static LoadingCache<Long,String> loadCache(CacheLoader<Long,String> cacheLoader) throws Exception {
    LoadingCache<Long,String> cache = CacheBuilder.newBuilder()
        //缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
        .maximumSize(GUAVA_CACHE_SIZE)
        //设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
        .expireAfterAccess(GUAVA_CACHE_DAY,TimeUnit.DAYS)
        // 设置缓存在写入之后 设定时间 后失效
        .expireAfterWrite(GUAVA_CACHE_DAY,TimeUnit.DAYS)
        //移除监听器,缓存项被移除时会触发
        .removalListener(new RemovalListener<Long,String>() {
          @Override
          public void onRemoval(RemovalNotification<Long,String> rn) {
            //逻辑操作
          }
        })
        //开启Guava Cache的统计功能
        .recordStats()
        .build(cacheLoader);
    return cache;
  }

  /**
   * 设置缓存值
   * 注: 若已有该key值,则会先移除(会触发removalListener移除监听器),再添加
   *
   * @param key
   * @param value
   */
  public static void put(Long key,String value) {
    try {
      GLOBAL_CACHE.put(key,value);
    } catch (Exception e) {
      log.error("设置缓存值出错",e);
    }
  }

  /**
   * 批量设置缓存值
   *
   * @param map
   */
  public static void putAll(Map<? extends Long,? extends String> map) {
    try {
      GLOBAL_CACHE.putAll(map);
    } catch (Exception e) {
      log.error("批量设置缓存值出错",e);
    }
  }

  /**
   * 获取缓存值
   * 注:如果键不存在值,将调用CacheLoader的load方法加载新值到该键中
   *
   * @param key
   * @return
   */
  public static String get(Long key) {
    String token = "";
    try {
      token = GLOBAL_CACHE.get(key);
    } catch (Exception e) {
      log.error("获取缓存值出错",e);
    }
    return token;
  }

  /**
   * 移除缓存
   *
   * @param key
   */
  public static void remove(Long key) {
    try {
      GLOBAL_CACHE.invalidate(key);
    } catch (Exception e) {
      log.error("移除缓存出错",e);
    }
  }

  /**
   * 批量移除缓存
   *
   * @param keys
   */
  public static void removeAll(Iterable<Long> keys) {
    try {
      GLOBAL_CACHE.invalidateAll(keys);
    } catch (Exception e) {
      log.error("批量移除缓存出错",e);
    }
  }

  /**
   * 清空所有缓存
   */
  public static void removeAll() {
    try {
      GLOBAL_CACHE.invalidateAll();
    } catch (Exception e) {
      log.error("清空所有缓存出错",e);
    }
  }

  /**
   * 获取缓存项数量
   *
   * @return
   */
  public static long size() {
    long size = 0;
    try {
      size = GLOBAL_CACHE.size();
    } catch (Exception e) {
      log.error("获取缓存项数量出错",e);
    }
    return size;
  }
}

3、 Usage Summary

1. Removal mechanism

Data removal in guava cache includes passive removal and active removal.

There are three types of passive removal:

Size based removal: when the quantity reaches the specified size, the infrequent key values will be removed

Time based removal: expireafteraccess (long, timeunit) is removed according to the time after the last access of a key value pair. Expireafterwrite (long, timeunit) is removed according to the time after a key value pair is created or the value is replaced

Reference based removal: it is mainly a Java based garbage collection mechanism, which determines the removal according to the reference relationship of keys or values

There are three types of active removal: 1) Remove separately: cache invalidate(key)

         2). Batch remove: cache invalidateAll(keys)

         3). Remove all: cache invalidateAll()

If the remove listener removallistener is configured, the logic under the listener will be executed synchronously when all the actions are removed.

To change to asynchronous, use: removallisteners asynchronous(RemovalListener,Executor)

2. Problems encountered

Before the put operation, if the key value already exists, it will trigger removallistener to remove the listener, and then add and configure expireafteraccess and expireafterwrite, but it will not be removed after the specified time.

Solution: the cache built by cachebuilder will not automatically clean up and recycle at a specific time, nor will it clean up immediately after a cache item expires. It will not start a thread for cache maintenance because a) the thread is relatively heavy, and b) some environments restrict the creation of threads. It does a small amount of maintenance during write operations, or occasionally during read operations. Of course, you can also create your own maintenance thread to call cache at fixed intervals cleanUp()。

The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>