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.
 *
 * <p>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<K, V> 

从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<String, List<Integer>>  {

    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<Integer> load(String key) {
        long startTime = System.currentTimeMillis();
        List<Integer> result = (一般为数据库操作,获取数据)
        return result;
    }

    @Override
    public ListenableFuture<List<Integer>> reload(String key, List<Integer> 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<String, List<Integer>> 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<K, V> {
...
  public abstract V load(K key) throws Exception;
}

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值