zoukankan      html  css  js  c++  java
  • guava缓存

    在项目中,如果想把某些数据放到内存缓存中,并且支持自动过期,则可以用guava cache。

    要用到的类和接口有CacheBuilder、CacheLoader、Cache、LoadingCache,其中LoadingCache是Cache的子接口。

    Cache接口方法有:

    V get(K key, Callable<V> loader) throws ExecutionException:从缓存中取指定key对应的值,如果不存在就调用loader加载进缓存,再返回。如果同时有多个线程调用此get()方法,且恰好此时缓存中没有对应的值,则只会有一个线程去加载数据,其他线程会等待,直到缓存中有数据,读取并返回。这样的操作模式,虽然比多个线程都去加载数据好一些,但是依然有些问题。假如并发大的话,会hang住所有线程,导致系统在一定时间内不能提供服务。

    示例:

    public class Test {
        public static void main(String[] args) throws ExecutionException {
            Cache<String, Object> cache = CacheBuilder.newBuilder().build();
            Object object = cache.get("first", Test::getFirst);
            System.out.println(object);
            object = cache.get("first", Test::getFirst);
            System.out.println(object);
        }
    
        private static List<String> getFirst() {
            System.out.println("getFirst");
            return Lists.newArrayList(UUID.randomUUID().toString(), UUID.randomUUID().toString());
        }
    
    }

    V getIfPresent(Object key):从缓存中取指定key对应的值,如果不存在就返回null,而不会去加载数据。

    ImmutableMap getAllPresent(Iterable keys):从缓存中取多个key对应的值。如果某个key对应的值不存在,则返回的Map不包含此键。极端情况下,返回一个空Map。

    void put(K, V):把一个键值对放到缓存中。不推荐用这个方法,推荐优先使用get(K key, Callable<V> loader)方法。

    void putAll(Map<K, V> map):把一堆键值对放到缓存中。

    void invalidate(Object key):从缓存中移除某个key对应的值。

    void invalidateAll(Iterable keys):从缓存中移除多个key对应的值。

    void invalidateAll():从缓存中移除所有key对应的值,也就是清空缓存。

    long size():返回缓存中key的个数。是个大概数,不完全精确。

    CacheStats stats():返回一个CacheStats实例,通过这个实例可以得到命中缓存次数、未命中缓存的次数等等,前提是创建Cache时调用了CacheBuilder的recordStats()方法。我们可以用这个做缓存的监控。

    示例:

        public static void main(String[] args) throws ExecutionException {
            Cache<String, String> cc = CacheBuilder.newBuilder().recordStats().build();
            cc.get("a", () -> UUID.randomUUID().toString());
            cc.get("b", () -> UUID.randomUUID().toString());
            ImmutableMap ss = cc.getAllPresent(Sets.newHashSet("a", "b", "c", "d"));
            System.out.println(ss);
        }

    注意,Cache没有get(K key)方法,用getIfPresent(K key)就行。

    LoadingCache接口继承了Cache接口,除了继承自Cache接口的全部方法外,自己定义的方法有:

    V get(K key) throws ExecutionException:从缓存中获取key对应的值,如果不存在,就调用CacheLoader实例的方法加载数据进缓存。同样的,如果有多个线程同时get同一个key,也只会有一个线程去加载,其他线程会阻塞,直到缓存中有数据,读取并返回。如果有多个线程同时get多个key,则每个key都会有一个线程去加载对应数据,其他多余线程阻塞直至对应key有数据,读取并返回。

    V getUnchecked(K key):效果同get(K key)方法,只是不抛ExecutionException异常。

    ImmutableMap<K, V> getAll(Iterable<K> keys) throws ExecutionException:从缓存中获取多个key对应的值,哪个key对应的数据不存在,会去加载这个key对应的数据。

    void refresh(K key):重新加载key对应的数据进缓存。refresh会根据当前缓存中有没有对应的数据执行不同的逻辑:如果当前缓存中有对应的数据,则会调用CacheLoader实例的reload()方法。否则会调用CacheLoader实例的load()方法。在refresh期间,如果有读请求,则会返回老值。如果没有老值,则会阻塞,等待refresh完成。如果reload()或者load()是异步的,则可能会返回null。

    ConcurrentMap asMap():查看缓存中数据的视图。

    示例:

        LoadingCache<Integer, Map<Integer, List<Long>>> allChannelPhotoCache = CacheBuilder.newBuilder()
                .concurrencyLevel(8)
                .initialCapacity(8)
                .maximumSize(100)
                .build(new CacheLoader<Integer, Map<Integer, List<Long>>>() {
                           @Override
                           public Map<Integer, List<Long>> load(Integer key) {
                               monitorLogger.info("currentThread= " + Thread.currentThread().getName() + ", load cache key= " + key);
                               if (1 == key) {
                                   return getChannelPhotoIds();
                               } else {
                                   return new HashMap<>(0);
                               }
                           }
                       }
                );

    通过CacheBuilder.newBuilder().build(CacheLoader loader)创建一个Cache实例,具体类型是LocalCache类中的LocalLoadingCache内部类。

    CacheBuilder.newBuilder()生成一个CacheBuilder实例。CacheBuilder有很多实例方法:

    CacheBuilder concurrencyLevel(int concurrencyLevel):设置更新缓存的并发度,默认是4。会根据并发度的值把哈希表分段,每个段都有一个分段锁,用于控制对这一段数据的更新。

    CacheBuilder initialCapacity(int initialCapacity):设置哈希表的初始容量,默认值是16。

    CacheBuilder maximumSize(int maximumSize):设置哈希表最多能放的键值对数量。

  • 相关阅读:
    四、单片机学习——矩阵键盘实验
    二、单片机学习——独立按键实验
    三、单片机学习——数码管实验(共阳)
    一、单片机学习——流水灯实验
    Cacti监控Linux安装配置snmp服务
    firewalld和iptables区别
    Zabbix图形界面乱码修复为中文显示
    Centos7安装Zabbix 5.0 LTS 版本安装(详细版)
    Ubuntu Server 18.04 网络配置
    linux下开启root用户远程登录,允许无密码登录
  • 原文地址:https://www.cnblogs.com/koushr/p/11942415.html
Copyright © 2011-2022 走看看