源码包的简单说明:
com.google.common.annotations: 普通注解类型
com.google.common.base: 基本工具类库和接口
com.google.common.cache: 缓存工具包, 非常简单易用且功能强大的 JVM 内缓存
com.google.common.collect: 带泛型的集合接口扩展和实现, 以及工具类, 这里你会发现很多好玩的集合
com.google.common.eventbus: 发布订阅风格的事件总线
com.google.common.hash: 哈希工具包
com.google.common.io:I/O 工具包
com.google.common.math: 原始算术类型和超大数的运算工具包
com.google.common.net: 网络工具包
com.google.common.primitives: 八种原始类型和无符号类型的静态工具包
com.google.common.reflect: 反射工具包
com.google.common.util.concurrent: 多线程工具包
- import com.google.common.cache.CacheBuilder;
- import com.google.common.cache.CacheLoader;
- import com.google.common.cache.LoadingCache;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.util.concurrent.TimeUnit;
- /**
- * Created by hxiuz on 2018/2/10.
- */
- public class TokenCache {
- private static Logger logger = LoggerFactory.getLogger(TokenCache.class);
- // 超过 10000 则使用 LRU 算法 [缓存淘汰算法] 进行清除缓存
- public static LoadingCache < String,
- String > localCache = CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(10000).expireAfterAccess(10, TimeUnit.MINUTES).build(new CacheLoader < String, String > () {
- // 默认的数据加载实现, 当调用 get 取值时, 若 key 没有对应的值, 则调用此方法加载
- @Override public String load(String s) throws Exception {
- return "null";
- }
- });
- public static void setKey(String key, String value) {
- localCache.put(key, value);
- }
- public static String getKey(String key) {
- String value = null;
- try {
- value = localCache.get(key);
- if ("null".equals(value)) {
- return null;
- }
- return value;
- } catch(Exception e) {
- // 打印异常堆栈
- logger.error("localCache get ERROR", e);
- }
- return null;
- }
- }
LRU 算法拓展
原理
LRU(Least recently used, 最近最少使用的)算法根据数据的历史访问记录来进行淘汰数据, 其核心思想是如果数据最近被访问过, 那么将来被访问的几率也更高
实现图示
最常见的实现是使用一个链表保存缓存数据, 详细算法实现如下:
1. 新数据插入到链表头部;
2. 每当缓存命中(即缓存数据被访问), 则将数据移到链表头部;
3. 当链表满的时候, 将链表尾部的数据丢弃
分析
命中率
当存在热点数据时, LRU 的效率很好, 但偶发性的周期性的批量操作会导致 LRU 命中率急剧下降, 缓存污染情况比较严重
复杂度
实现简单
代价
命中时需要遍历链表, 找到命中的数据块索引, 然后需要将数据移到头部
来源: http://www.bubuko.com/infodetail-2494508.html