Guava LoadingCache用法

项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.Guava中的cache

cache在任何系统中都是一种被广泛使用的数据中间件。对于小规模的缓存数据,Guava中的cache会很实用,使用得也很多。下面我们就针对Guava中的cache做个简单分析。

/**
 * A semi-persistent mapping from keys to values. Cache entries are manually added using
 * {@link #get(Object, Callable)} or {@link #put(Object, Object)}, and are stored in the cache until
 * either evicted or manually invalidated.
 *
 * 

Implementations of this interface are expected to be thread-safe, and can be safely accessed * by multiple concurrent threads. * * @author Charles Fry * @since 10.0 */ @GwtCompatible public interface Cache

从jdk源码中的注释里,我们可以得到如下信息:
1.Cache接口是一种半持久化的KV结构。
2.Cache可以使用get(Object, Callable)方法或者put方法手动添加元素对。
3.这些KV会一直有效,直到被驱逐或者手动设置为无效。
4.该接口事线程安全的,可以被多个线程并发访问。

2.LoadingCache

Guava Cache与ConcurrentMap比较相似,最大的不同在于ConcurrentMap会一直保存添加的元素直到被手动移除。而Guava Cache为了限制内存的使用会自动回收元素,而且在很多场景下,需要自动加载缓存,这也是对比ConcurrentMap的优势。

LoadingCache继承了Cache接口。LoadingCache读取一个指定key的数据时,如果key不存在,LoadingCache会执行加载数据到缓存。

3.LoadingCache例子

import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;

import java.util.List;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyCacheLoader extends CacheLoader>  {

    private final ListeningExecutorService executorService =
            MoreExecutors.listeningDecorator(new ThreadPoolExecutor(16,
                    100,
                    60,
                    TimeUnit.SECONDS,
                    new SynchronousQueue<>(),
                    new NamedThreadFactory("xxx")));

    protected ListeningExecutorService executorService() {
        return executorService;
    }

    @Override
    public List load(String key) {
        long startTime = System.currentTimeMillis();
        List result = (一般为数据库操作,获取数据)
        return result;
    }

    @Override
    public ListenableFuture> reload(String key, List oldValue) {
        return executorService().submit(() -> load(key));
    }

}


public class MyLoadingCache {

    private static final int CACHE_TTL = 60 * 6;
    private static final int CACHE_MAX_SIZE = 10000;

    private static LoadingCache> myLoadingCache = CacheBuilder.newBuilder()
            .refreshAfterWrite(CACHE_TTL, TimeUnit.MINUTES)
            .maximumSize(CACHE_MAX_SIZE)
            .build(new ReaderOnlineBadContentCacheLoader());
  }

LoadingCache类型的对象是通过CacheBuilder进行构建的,从构建过程中很明显可以看出来是使用的build模式,调用的每个方法返回的都是CacheBuilder本身,直到build方法被调用,才返回LoadingCache对象。

build方法需要传入一个CacheLoader对象,CacheLoader是一个抽象类,需要重写load方法。

@GwtCompatible(emulated = true)
public abstract class CacheLoader {
...
  public abstract V load(K key) throws Exception;
}

如果我们调用LoadingCache中的get方法,缓存不存在相对应的key的数据,那么CacheLoader会自动调用load方法去从外部加载数据进来。

你可能感兴趣的:(service,Guava,LoadingCache,缓存,CacheLoader)