当前位置 主页 > 网站技术 > 代码类 >

    如何基于LoadingCache实现Java本地缓存

    栏目:代码类 时间:2019-12-23 12:07

    这篇文章主要介绍了如何基于LoadingCache实现Java本地缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    前言

    Guava是Google开源出来的一套工具库。其中提供的cache模块非常方便,是一种与ConcurrentMap相似的缓存Map。

    官方地址:https://github.com/google/guava/wiki/CachesExplained

    开始构建

    一. 添加依赖

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

    二.创建 CacheLoader

    LoadingCache<Long, String> cache = CacheBuilder.newBuilder()
            //缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
            .maximumSize(GUAVA_CACHE_SIZE)
            //设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
            .expireAfterAccess(10, TimeUnit.MINUTES)
            //移除监听器,缓存项被移除时会触发
            .removalListener(new RemovalListener <Long, String>() {
              @Override
              public void onRemoval(RemovalNotification<Long, String> rn) {
                //执行逻辑操作
              }
            })
            //开启Guava Cache的统计功能
            .recordStats()
            .build(cacheLoader);

    三.个人封装的工具类

    package com.xxx;
    
    import com.google.common.cache.*;
    import org.slf4j.Logger;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.ConcurrentMap;
    import java.util.concurrent.TimeUnit;
    
    public class CacheManager {
    
      private static Logger log = Log.get();
    
      /** 缓存项最大数量 */
      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;
      }
    }