guava学习

新建一个Guava Cache

Guava API中提供了CacheBuilder来初始化一个cache。通常有两种实现方式:
如果没有提供CacheLoader的实现,则返回的Cache,否则返回的是LoadingCache。

private static final Cache<String,String> caches = CacheBuilder.newBuilder().maximumSize(3)
        .removalListener(myListener)
        .build();

private static finalLoadingCache<String, String> caches = CacheBuilder.newBuilder().maximumSize(3)
        .removalListener(myListener)
        .build(new CacheLoader<String, String>() {
            @Override
           public String load(String key) throws Exception {  // 注意,这里抛出了异常
                return MyLoadCache(key); 
           }       
        });

数据自动加载

数据自动加载的使用场景在如果在get(key)的时候,没有该元素,那么Guava Cache就会调用相应方法自动去根据key值计算出value并加入到缓存中再返回。Guava提供了两种自动加载的实现。
CacheLoader
如果有合理的默认方法来根据Key加载或者计算出相应的Value,那么应当使用CacheLoader。
自己实现的的CacheLoader通常只需要简单地实现V load(K key) throws Exception方法。然后在load方法中实现根据key来计算出相应的value的逻辑即可。
在调用get(key)方法的时候,要么返回已有的缓存值,要么就使用CacheLoader向缓存中原子性的加载新增。
由于CacheLoader可能抛出异常,LoadingCache.get(K)也声明为抛出ExecutionException异常。
如果你定义的CacheLoader没有声明任何检查型异常,则可以通过getUnchecked(K)查找缓存;但必须注意,一旦CacheLoader声明了检查型异常,就不可以调用getUnchecked(K)。

private static final LoadingCache<Integer, String> cache1 = CacheBuilder.
        newBuilder()
        .maximumSize(3)
        .build(new CacheLoader<Integer, String>() {
            @Override
           public String load(Integer key){  // 没有抛出异常
                return null;
            }
        });

private static String getUnchecked(Integer key) {
    return cache1.getUnchecked(key);    // 可以使用getUnchecked()
}

Cache.get(K, Callable<V>)
这个方法返回缓存中相应的值,或者用给定的Callable运算并把结果加入到缓存中。在整个加载方法完成前,缓存项相关的可观察状态都不会更改。这个方法简便地实现了模式"如果有缓存则返回;否则运算、缓存、然后返回"。

显示插入

Guava Cache同时也提供了put()方法用于显示插入数据使用cache.put(key,value)方法可以直接向缓存中插入值,这会直接覆盖掉给定键之前映射的值。

移除监听器

通过CacheBuilder.removalListener(RemovalListener), 可以申明一个监听器,以便缓存项被移除的时候做一些额外的操作。
比如,如果缓存的是BasicDataSource或者Connection,那么在移除时,需要调用close方法将其关闭,否则就会造成内存泄露。我们只需要实现RemovalListener接口并重写其onRemoval()方法即可,并且会获取通知RemovalNotification,RemovalNotification中包含了移除原因,建和值等。
注意:RemovalListener抛出的任何异常都会在记录到日志后被丢弃[swallowed]
注意:默认情况下,监听器方法是在移除缓存时同步调用的。因为缓存的维护和请求响应通常是同时进行的,代价高昂的监听器方法在同步模式下会拖慢正常的缓存请求。这种情况下,可以使用RemiValListener.asynchronous(RemovalListener, Executor)把监听器装饰为异步操作。

pom.xml配置

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>
</dependencies>

测试的小demo

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 java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;

public class GuavaDemo {

    private LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
            .maximumSize(1000).build(new CacheLoader<String, String>()
            {
                @Override
                public String load(String key) throws Exception   // !!!注意这里抛出异常
                {
                    String value = "<-- " + key + " -->";
                    System.out.println("Calculate the key : "+ value);
                    return value;
                }
            });

    /**
     * CacheLoader
     */
    public void loadingCache(String key)
    {


        String resultVal = null;
        try {
            resultVal = graphs.get(key);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        System.out.println(resultVal);
    }


    private Cache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(1000).build();

    /**
     *
     * Callable
     */
    public void callablex() throws ExecutionException
    {

        String result = cache.get("key", new Callable<String>()
        {
            public String call()
            {
                return "result";
            }
        });
        System.out.println(result);
    }

    public void callablex(String key, Callable<String> callAble) throws ExecutionException
    {

        String result = cache.get(key, callAble);
        System.out.println(result);
    }

    public static void main(String[] args) throws ExecutionException {
        GuavaDemo demo = new GuavaDemo();
        demo.loadingCache("key");
        demo.loadingCache("key");
        demo.loadingCache("key");

        demo.callablex("key", new Callable<String>() {
            public String call() throws Exception {
                return "<--1-->";
            }
        });
        demo.callablex("key", new Callable<String>() {
            public String call() throws Exception {
                return "<--2-->";
            }
        });
        demo.callablex("key1", new Callable<String>() {
            public String call() throws Exception {
                return "<--3-->";
            }
        });

    }
}
posted @ 2020-07-31 15:08  金牌厨师小庄  阅读(156)  评论(0)    收藏  举报