- guava cache 设计思想类似 concurrentHashMap(JDK 1.7版;JDK 1.8版已换成红黑树),使用多个segment细粒度锁,在保证线程安全的同时,支持多线程的高并发,类似map,存储键值对的集合,使用LRU(最近最少清除策略)。
案例一
package com.mmall.common; 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; public class TokenCache { private static Logger logger = LoggerFactory.getLogger(TokenCache.class); public static final String TOKEN_PREFIX = "token_"; // 初始化1000条容量,最大10000条容量且有效期为12小时的本地缓存,如果超过最大容量,则用LRU算法(最近最少使用)进行移除 private static LoadingCache<String,String> localCache = CacheBuilder.newBuilder().initialCapacity(1000).maximumSize(10000).expireAfterAccess(12, TimeUnit.HOURS) .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; } }
案例二
package com.mmall.concurrency.example.cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.TimeUnit; @Slf4j public class GuavaCacheExample1 { public static void main(String[] args) { LoadingCache<String, Integer> cache = CacheBuilder.newBuilder() .maximumSize(10) // 最多存放10个数据 .expireAfterWrite(10, TimeUnit.SECONDS) // 缓存10秒 .recordStats() // 开启记录状态数据功能 .build(new CacheLoader<String, Integer>() { @Override public Integer load(String key) throws Exception { return -1; } }); log.info("{}", cache.getIfPresent("key1")); // null cache.put("key1", 1); log.info("{}", cache.getIfPresent("key1")); // 1 cache.invalidate("key1"); log.info("{}", cache.getIfPresent("key1")); // null try { log.info("{}", cache.get("key2")); // -1 cache.put("key2", 2); log.info("{}", cache.get("key2")); // 2 log.info("{}", cache.size()); // 1 for (int i = 3; i < 13; i++) { cache.put("key" + i, i); } log.info("{}", cache.size()); // 10 log.info("{}", cache.getIfPresent("key2")); // null Thread.sleep(11000); log.info("{}", cache.get("key5")); // -1 log.info("{},{}", cache.stats().hitCount(), cache.stats().missCount()); log.info("{},{}", cache.stats().hitRate(), cache.stats().missRate()); } catch (Exception e) { log.error("cache exception", e); } } }
案例三
package com.mmall.concurrency.example.cache; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; @Slf4j public class GuavaCacheExample2 { public static void main(String[] args) { Cache<String, Integer> cache = CacheBuilder.newBuilder() .maximumSize(10) // 最多存放10个数据 .expireAfterWrite(10, TimeUnit.SECONDS) // 缓存10秒 .recordStats() // 开启记录状态数据功能 .build(); log.info("{}", cache.getIfPresent("key1")); // null cache.put("key1", 1); log.info("{}", cache.getIfPresent("key1")); // 1 cache.invalidate("key1"); log.info("{}", cache.getIfPresent("key1")); // null try { log.info("{}", cache.get("key2", new Callable<Integer>() { @Override public Integer call() throws Exception { return -1; } })); // -1 cache.put("key2", 2); log.info("{}", cache.get("key2", new Callable<Integer>() { @Override public Integer call() throws Exception { return -1; } })); // 2 log.info("{}", cache.size()); // 1 for (int i = 3; i < 13; i++) { cache.put("key" + i, i); } log.info("{}", cache.size()); // 10 log.info("{}", cache.getIfPresent("key2")); // null Thread.sleep(11000); log.info("{}", cache.get("key5", new Callable<Integer>() { @Override public Integer call() throws Exception { return -1; } })); // -1 log.info("{},{}", cache.stats().hitCount(), cache.stats().missCount()); log.info("{},{}", cache.stats().hitRate(), cache.stats().missRate()); } catch (Exception e) { log.error("cache exception", e); } } }