今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

guava缓存使用

1.概述

guava cache是基于java的本地缓存,使用缓存的目的是为了系统响应更快。以下是guava cache中相关的类

2.使用

2.1CacheLoader 创建

使用from方法创建,或者使用构造器,需要实现load方法

 CacheLoader getCacheLoader(){
       return  CacheLoader.from(key->key.toString().toUpperCase());
 }

new CacheLoader() {
	@Override
	public Object load(Object key) throws Exception {
		return key.toString().toUpperCase();
	}
};

2.2 LoadingCache使用

    @Test
    public void useLoadingCache() {
        CacheLoader<String, String> loader;
        loader = getCacheLoader();

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder().build(loader);

        assertEquals(0, cache.size());
        assertEquals("HELLO", cache.getUnchecked("hello"));
        assertEquals(1, cache.size());
    }

2.3设置最大缓存数

可以使用CacheBuilderSpec设置,或者使用CacheBuilder.newBuilder().maximumSize(),如下设置最大数为3,当存取第四个是第一个会过期

    @Test
    public void setCacheMaximumSize() {
        CacheLoader<String, String> loader;
        loader = getCacheLoader();
        LoadingCache<String, String> cache;
        //使用CacheBuilderSpec
        cache= CacheBuilder.from(CacheBuilderSpec.parse("maximumSize=3")).build(loader);

        cache.getUnchecked("first");
        cache.getUnchecked("second");
        cache.getUnchecked("third");
        cache.getUnchecked("forth");
        assertEquals(3, cache.size());
        assertNull(cache.getIfPresent("first"));
        assertEquals("FORTH", cache.getIfPresent("forth"));
    }

2.4 设置MaxWeight

达到设置的阈值时,缓存过期。以下实列中权重设置的时缓存值的长度

    @Test
    public void setCacheMaxWeight() {
        CacheLoader<String, String> loader;
        loader = getCacheLoader();
        Weigher<String, String> weighByLength;
        weighByLength = (key, value) -> value.length();

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder()
                .maximumWeight(16)
                .weigher(weighByLength)
                .build(loader);

        cache.getUnchecked("first");
        cache.getUnchecked("second");
        cache.getUnchecked("third");
        cache.getUnchecked("last");
        assertEquals(3, cache.size());
        assertNull(cache.getIfPresent("first"));
        assertEquals("LAST", cache.getIfPresent("last"));

2.5 通过时间来过期缓存

expireAfterAccess指访问后单位时间过期,也可以设置expireAfterWrite,即被写后多长时间过期

    @Test
    public void expireAfterTime()
            throws InterruptedException {
        CacheLoader<String, String> loader;
        loader = getCacheLoader();

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder()
                .expireAfterAccess(2, TimeUnit.MILLISECONDS)
                .build(loader);

        cache.getUnchecked("hello");
        assertEquals(1, cache.size());

        cache.getUnchecked("hello");
        Thread.sleep(300);

        cache.getUnchecked("test");
        assertEquals(1, cache.size());
        assertNull(cache.getIfPresent("hello"));
    }

2.6 弱key引用weakKeys

垃圾回收时会对所引用所对应的缓存值回收。

    @Test
    public void weakKeyHasNoRef() throws InterruptedException {
        CacheLoader<MyKey, String> loader=CacheLoader.from(key->key.getKey()+" reference");
        LoadingCache<MyKey, String> cache = CacheBuilder.newBuilder().weakKeys().build(loader);
        MyKey key = new MyKey("weak");

        String value = cache.getUnchecked(key);
        assertEquals(value,"weak reference");
        key=null;
        System.gc();
        TimeUnit.SECONDS.sleep(2);
        assertEquals(1,cache.size());
        System.out.println(cache.asMap());
    }

    @Data
    private static class MyKey{
        String key;

        public MyKey(String key) {
            this.key = key;
        }
    }

2.7 刷新缓存

可以使用自动刷新和手动刷新

   @Test
   void  refreshCache() throws ExecutionException {
        //自动刷新
       CacheLoader<String, String> loader;
       loader =getCacheLoader();

       LoadingCache<String, String> cache;
       cache = CacheBuilder.newBuilder()
                .refreshAfterWrite(1,TimeUnit.MINUTES)
                .build(loader);

       //手动刷新
       String value = cache.get("key");
       cache.refresh("key");
   }

2.8 使用putAll方法

    @Test
    public void usePutAll() {
        CacheLoader<String, String> loader;
        loader = getCacheLoader();

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder().build(loader);

        Map<String, String> map = new HashMap<>();
        map.put("first", "FIRST");
        map.put("second", "SECOND");
        cache.putAll(map);

        assertEquals(2, cache.size());
    }

2.9使用Listener 监听缓存的变化

    @Test
    public void useListener() {
        CacheLoader<String, String> loader;
        loader =  getCacheLoader();

        RemovalListener<String, String> listener;
        listener = n -> {
            if (n.wasEvicted()) {
                String cause = n.getCause().name();
                assertEquals(RemovalCause.SIZE.toString(),cause);
            }
        };

        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder()
                .maximumSize(3)
                .removalListener(listener)
                .build(loader);

        cache.getUnchecked("first");
        cache.getUnchecked("second");
        cache.getUnchecked("third");
        cache.getUnchecked("last");
        assertEquals(3, cache.size());
    }

2.10 使用Forwarding

forwarding相当于对底层缓存的装饰,以便我们可以自己重新缓存实现。

public class LoggingForwardingCache<K, V> extends ForwardingCache.SimpleForwardingCache<K, V> {
    private final Logger logger = Logger.getLogger(LoggingForwardingCache.class.getName());

    public LoggingForwardingCache(Cache<K, V> delegate) {
        super(delegate);
    }


    @Override
    public V getIfPresent(Object key) {
        V value = super.getIfPresent(key);
        if (value != null) {
            logger.info("Cache hit for key: " + key);
        }
        return value;
    }
}    

----------------

@Test
    public void useForwarding(){
        Cache<String, Object> cache =
                CacheBuilder.newBuilder()
                .maximumSize(1000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build();

        LoggingForwardingCache<String, Object> loggingCache = new LoggingForwardingCache<>(cache);
        loggingCache.put("forward","loggingCache");
        Object forward = loggingCache.getIfPresent("forward");
        assertEquals("loggingCache",forward);
    }

3.总结

在上面的例子中,主要介绍了guava缓存的基本用法,在新版本中也是更新了lamda的方法,所以主要以lamda方式去创建CacheLoader。并且通过junit的静态方法去验证缓存预期是不是正确。

分享到:

专栏

类型标签

网站访问总量