Guava LoadingCache使用记录

LoadingCache可替换Map作为系统的缓存,相比于Map提供了数据自动回收功能,当然还有诸如数据删除监听、数据更新等功能,具体使用方式见代码与注释:

package com.zte.sunquan.demo.test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalListeners;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Lists;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by sunquan on 2017/11/20.
 */
public class H2Test {
    //simulate data
    List list = Lists.newArrayList("a", "b", "c", "d", "e", "f", "g", "h", "j", "k", "m");

    private String compute(Integer key) {
        System.out.println(Thread.currentThread().getName() + "-compute value with " + key);
        return list.get(key);
    }


    @Test
    public void testCache1() throws ExecutionException {
        Cache cache = CacheBuilder.newBuilder().build();
        cache.put(0, "a");
        cache.put(1, "b");
        cache.put(2, "c");
        cache.put(3, "d");
        System.out.println(cache.getIfPresent(0));//a
        System.out.println(cache.getIfPresent(-1));//null
        System.out.println(cache.get(-1, () -> "bb"));//bb (无指定key的value,则执行callable,并将计算值加入缓存)
        System.out.println(cache.getIfPresent(-1));//bb
    }

    @Test
    public void testCache3() throws ExecutionException, InterruptedException {
        LoadingCache cache = CacheBuilder.newBuilder()
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔1秒进行数据更新,会执行compute重新计算
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.SECONDS);
        System.out.println("v1:" + cache.get(1));
        cache.invalidate(1);//消除key为1的缓存
        Thread.sleep(2000);
        System.out.println("v2:" + cache.get(1));//重新执行compute
    }

    @Test
    public void testCache2() throws ExecutionException, InterruptedException {
        LoadingCache cache = CacheBuilder.newBuilder()
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔1秒进行数据更新,会执行compute重新计算
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.SECONDS);
        System.out.println("v1:" + cache.get(1));
        Thread.sleep(1000);
        System.out.println("v2:" + cache.get(1));
        Thread.sleep(5000);
    }


    @Test
    public void testCache4() throws ExecutionException, InterruptedException {
        //增加缓存值删除监听器
        LoadingCache cache = CacheBuilder.newBuilder()
                .removalListener(new RemovalListener() {
                    @Override
                    public void onRemoval(RemovalNotification removalNotification) {
                        System.out.println(Thread.currentThread().getName() + "-remove key:" + removalNotification.getKey());
                        System.out.println(Thread.currentThread().getName() + "-remove value:" + removalNotification.getValue());
                    }
                })
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔1秒进行数据更新,会执行compute重新计算(注意refresh会触发删除操作)
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.SECONDS);
        System.out.println("v1:" + cache.get(1));
        Thread.sleep(1000);
        System.out.println("v2:" + cache.get(1));
        Thread.sleep(3000);

        cache.invalidateAll();//invalidate亦会触发删除操作
        Thread.sleep(3000);
    }

    @Test
    public void testCache5() throws ExecutionException, InterruptedException {
        //增加缓存值删除监听器
        LoadingCache cache = CacheBuilder.newBuilder()
                .removalListener(new RemovalListener() {
                    @Override
                    public void onRemoval(RemovalNotification removalNotification) {
                        System.out.println(Thread.currentThread().getName() + "-remove key:" + removalNotification.getKey());
                        System.out.println(Thread.currentThread().getName() + "-remove value:" + removalNotification.getValue());
                    }
                }).recordStats()
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔1秒进行数据更新,会执行compute重新计算(注意refresh会触发删除操作)
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.SECONDS);
        System.out.println("v1:" + cache.get(1));
        Thread.sleep(1000);
        System.out.println("v2:" + cache.get(1));
        Thread.sleep(3000);

        cache.invalidateAll();//invalidate亦会触发删除操作
        Thread.sleep(3000);
        System.out.println(cache.stats());
    }

    @Test
    public void testCache6() throws ExecutionException, InterruptedException {
        RemovalListener listener = RemovalListeners.asynchronous(new RemovalListener() {
            @Override
            public void onRemoval(RemovalNotification removalNotification) {
                System.out.println(Thread.currentThread().getName() + "-remove key:" + removalNotification.getKey());
                System.out.println(Thread.currentThread().getName() + "-remove value:" + removalNotification.getValue());
            }
        }, Executors.newSingleThreadExecutor());
        //增加缓存值删除异步监听器
        LoadingCache cache = CacheBuilder.newBuilder()
                .removalListener(listener).recordStats()
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔1秒进行数据更新,会执行compute重新计算(注意refresh会触发删除操作)
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.SECONDS);
        System.out.println("v1:" + cache.get(1));
        Thread.sleep(1000);
        System.out.println("v2:" + cache.get(1));
        Thread.sleep(3000);

        cache.invalidateAll();//invalidate亦会触发删除操作
        Thread.sleep(3000);
        System.out.println(cache.stats());
        cache.cleanUp();
    }  
}


具体使用,建议加入定时更新(如果compute计算逻辑不固定)

  @Test
    public void testCache7() throws ExecutionException, InterruptedException {
        ScheduledExecutorService exe = Executors.newScheduledThreadPool(1);
        //增加缓存值删除异步监听器
        LoadingCache cache = CacheBuilder.newBuilder()
                .build(new CacheLoader() {
                    //cache for what
                    public String load(Integer key) {
                        return compute(key);
                    }
                });
        //每隔5分钟进行数据更新,会执行compute重新计算(注意refresh会触发删除操作)
        exe.scheduleAtFixedRate(() -> cache.asMap().keySet().forEach(cache::refresh), 0, 1, TimeUnit.MINUTES);
        System.out.println("v1:" + cache.get(1));
        Thread.sleep(1000);
        System.out.println("v2:" + cache.get(1));
        Thread.sleep(3000);
        cache.invalidateAll();//invalidate亦会触发删除操作
        Thread.sleep(3000);
        cache.cleanUp();
    }


你可能感兴趣的:(Java基础)