【guava】cache
Cache
public class Solution { public static void main(String... arg) { //cache Cache<String, String> cacher = CacheBuilder.newBuilder() .maximumSize(1) .weakValues()//弱引用 .expireAfterWrite(5, TimeUnit.SECONDS)//写过期 //.expireAfterAccess(5,TimeUnit.SECONDS) //访问过期 .recordStats() .removalListener(new RemovalListener<String, String>() { @Override public void onRemoval(RemovalNotification<String, String> removalNotification) { System.out.println("remove: " + removalNotification.getKey() + "-" + removalNotification.getValue()); } }) .build(); //value = null 会抛异常 cacher.put("key1", "value"); //获取缓存value System.out.println(cacher.getIfPresent("key1")); //如没有, 起线程去查询 //如有并发冲突,只会起一个线程 !!! try { String value2 = cacher.get("key2", new Callable<String>() { /** * value == null, 抛异常 */ @Override public String call() throws Exception { return "value"; } }); System.out.println(value2); } catch (ExecutionException e) { e.printStackTrace(); } //缓存失效 cacher.invalidate("key1"); cacher.invalidateAll(Lists.newArrayList("key1", "key2")); cacher.invalidateAll(); //打印日志 System.out.println(cacher.stats()); } }
LoadingCache
cache的子类。需要实现CacheLoader
public class Solution { public static void main(String... arg) { //1、cache LoadingCache<String, String> cacher = CacheBuilder.newBuilder() .maximumSize(10) .expireAfterWrite(1800, TimeUnit.SECONDS)//写过期 //.expireAfterAccess(5,TimeUnit.SECONDS) //访问过期 .recordStats() .build(new CacheLoader<String, String>() { /** * 2、 * cache.get, cache.getUnchecked 会调用此方法 * 并发冲突时,只会调用一次 */ @Override public String load(String s) throws Exception { System.out.println("load: " + s); return "value"; } /** * 3、 * cache.getAll会调用此方法 * 只会load未命中的key */ @Override public Map<String, String> loadAll( final Iterable<? extends String> ids) throws Exception { System.out.println("loadAll: " + StringUtils.join(ids, "-")); Map<String, String> map = Maps.newHashMap(); ids.forEach(id -> map.put(id, "value")); return map; } }); //4、如没有则调用CacheLoader load方法 //5、getUnchecked 与 get的区别在于 抛出unchecked异常 cacher.getUnchecked("key1"); try { cacher.get("key1"); } catch (ExecutionException e) { e.printStackTrace(); } //6、批量查询。查询多个key, 每个key 执行一次load方法 try { cacher.getAll(Lists.newArrayList("key1", "key2", "key3")).forEach((k, v) -> { System.out.println(k + "-" + v); }); } catch (ExecutionException e) { e.printStackTrace(); } } }
搭配Optional使用(避免value为空的情况)
public class Solution { public static void main(String... arg) { //cache Cache<String, Optional<String>> cacher = CacheBuilder.newBuilder() .maximumSize(1) .weakValues()//弱引用 .expireAfterWrite(5, TimeUnit.SECONDS)//写过期 //.expireAfterAccess(5,TimeUnit.SECONDS) //访问过期 .recordStats() .build(); try { Optional<String> valueOpt = cacher.get("key1", new Callable<Optional<String>>() { @Override public Optional<String> call() throws Exception { return Optional.empty(); } }); cacher.getIfPresent("key1") .ifPresentOrElse(v -> System.out.println("return " + v) , () -> System.out.println("return null")); } catch (ExecutionException e) { e.printStackTrace(); } } }