使用guava实现找回密码的tokenCache以及LRU算法
源码包的简单说明:
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命中率急剧下降,缓存污染情况比较严重。
【复杂度】
实现简单。
【代价】
命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。