guava cache使用例子
关于介绍请参考:http://blog.csdn.net/liangrui1988/article/details/46120533#
下面是测试代码 ,下载源码可在github上获取:https://github.com/liangrui1988/guavaTest
package org.rui.test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import org.junit.Test; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.cache.Weigher; /** * Guava Cache有两种创建方式: * * 1. cacheLoader 2. callable callback * * 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key * X的值,如果该值已经缓存过了,则返回缓存中的值 * ,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的 * ,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定。 * * @author liangrui * */ public class Tests { /** * CacheLoader */ @Test public void loadingCache() { LoadingCache<String, String> graphs = CacheBuilder.newBuilder() .maximumSize(1000).build(new CacheLoader<String, String>() { @Override public String load(String key) throws Exception { System.out.println("key:"+key); if("key".equals(key)){ return "key return result"; }else{ return "get-if-absent-compute"; } } }); String resultVal = null; try { resultVal = graphs.get("key"); } catch (ExecutionException e) { e.printStackTrace(); } System.out.println(resultVal); } /** * * Callable * 在使用缓存前,首先问自己一个问题:有没有合理的默认方法来加载或计算与键关联的值?如果有的话,你应当使用CacheLoader。如果没有, * 或者你想要覆盖默认的加载运算,同时保留"获取缓存-如果没有-则计算"[get-if-absent-compute]的原子语义, * 你应该在调用get时传入一个Callable实例 * 。缓存元素也可以通过Cache.put方法直接插入,但自动加载是首选的,因为它可以更容易地推断所有缓存内容的一致性。 */ @Test public void callablex() throws ExecutionException { Cache<String, String> cache = CacheBuilder.newBuilder() .maximumSize(1000).build(); String result = cache.get("key", new Callable<String>() { public String call() { return "result"; } }); System.out.println(result); } /** * 从LoadingCache查询的正规方式是使用get(K)方法。这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地加载新值。 * 由于CacheLoader可能抛出异常,LoadingCache.get(K)也声明为抛出ExecutionException异常。 * 如果你定义的CacheLoader没有声明任何检查型异常 * ,则可以通过getUnchecked(K)查找缓存;但必须注意,一旦CacheLoader声明了检查型异常 * ,就不可以调用getUnchecked(K)。 * * @throws ExecutionException */ @Test public void capacity() { LoadingCache<String, String> graphs = CacheBuilder.newBuilder() .maximumWeight(100000).weigher(new Weigher<String, String>() { public int weigh(String k, String g) { return 100; } }).build(new CacheLoader<String, String>() { public String load(String key) { // no checked exception // return createExpensiveGraph(key); return "xxxx"; } }); } }
package org.rui.test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.junit.Test; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheStats; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; import com.google.common.cache.Weigher; /** * cache的参数说明: * * 回收的参数: 1. 大小的设置:CacheBuilder.maximumSize(long) * CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long) 2. * 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit) 3. * 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues() * CacheBuilder.softValues() 4. 明确的删除:invalidate(key) invalidateAll(keys) * invalidateAll() 5. 删除监听器:CacheBuilder.removalListener(RemovalListener) * * refresh机制: 1. LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。 2. * CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value 3. * CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache * * */ public class Eviction { /** * 基于容量的回收 * * * maximumSize(1) 缓存将尝试回收最近没有使用或总体上很少使用的缓存项 * * 不同的缓存项有不同的“权重”(weights)——例如,如果你的缓存值 * ,占据完全不同的内存空间,你可以使用CacheBuilder.weigher(Weigher)指定一个权重函数 * */ @Test public void callablex() throws ExecutionException, InterruptedException { // .maximumSize(100) Cache<String, User2> cache = CacheBuilder.newBuilder().maximumWeight(5) .weigher(new Weigher<String, User2>() { @Override public int weigh(String arg0, User2 user) { return 3; } }).removalListener(new RemovalListener<String, User2>() { @Override public void onRemoval(RemovalNotification<String, User2> rn) { System.out.println(rn.getKey() + "==被移除"); } }).build(); User2 result = cache.get("key", new Callable<User2>() { public User2 call() { return new User(1, "liang"); } }); // Thread.sleep(10000); User result2 = (User) cache.get("key2", new Callable<User2>() { public User2 call() { return new User(2, "liang2"); } }); User result3 = (User) cache.get("key3", new Callable<User>() { public User call() { return new User(3, "liang3"); } }); System.out.println(result); System.out.println(result2); System.out.println(result3); System.out.println(cache.size()); } /** * * * 定时回收(Timed Eviction) expireAfterAccess(long, * TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。 * expireAfterWrite(long, * TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。 * * * * // .expireAfterWrite(5, TimeUnit.SECONDS)//给定时间内没有写访问,则回收。 27 // * .expireAfterAccess(3, TimeUnit.SECONDS)// 缓存过期时间为3秒 * * @param args */ Cache<String, User2> cache2 = CacheBuilder.newBuilder().maximumSize(100) .expireAfterWrite(3, TimeUnit.MILLISECONDS) // .expireAfterAccess(3000, TimeUnit.MILLISECONDS) .removalListener(new RemovalListener<String, User2>() { @Override public void onRemoval(RemovalNotification<String, User2> rn) { System.out.println("Cause:" + rn.getCause() + " k: " + rn.getKey() + " v :" + rn.getValue() + "==被移除"); } }).build(); @Test public void timerEvication() throws ExecutionException, InterruptedException { User2 user = cache2.get("k1", new Callable<User2>() { @Override public User2 call() throws Exception { return new User(100, "hello"); } }); Thread.sleep(8000); System.out.println(cache2.size()); User2 user2 = cache2.get("k2", new Callable<User2>() { @Override public User2 call() throws Exception { return new User(200, "hello2"); } }); System.out.println(user); Thread.sleep(8000); user = cache2.get("k1", new Callable<User2>() { @Override public User2 call() throws Exception { return new User(10000000, "k1k1k1k1k1k1k1"); } }); System.out.println(cache2.size()); User2 user3 = cache2.get("k3", new Callable<User2>() { @Override public User2 call() throws Exception { return new User(300, "hello3"); } }); System.out.println(user); System.out.println(user2); System.out.println(user3); Thread.sleep(10000); System.out.println(cache2.size()); CacheStats status = cache2.stats(); status.missCount(); } /** * 显式清除 * * 任何时候,你都可以显式地清除缓存项,而不是等到它被回收: * * 个别清除:Cache.invalidate(key) 批量清除:Cache.invalidateAll(keys) * 清除所有缓存项:Cache.invalidateAll() * * @param args */ Cache<String, User2> cache3 = CacheBuilder.newBuilder().maximumSize(100) .removalListener(new RemovalListener<String, User2>() { @Override public void onRemoval(RemovalNotification<String, User2> rn) { System.out.println("Cause:" + rn.getCause() + " k: " + rn.getKey() + " v :" + rn.getValue() + "==被移除"); } }).build(); @Test public void clear() throws ExecutionException { User2 u = cache3.get("u1", new Callable<User2>() { @Override public User2 call() throws Exception { System.out.println("exec call>>>return result"); return new User(500, "world"); } }); System.out.println(u); u = cache3.get("u1", new Callable<User2>() { @Override public User2 call() throws Exception { System.out.println("exec call>>>return result"); return new User(500, "world"); } }); System.out.println(u); cache3.invalidate("u1"); u = cache3.get("u1", new Callable<User2>() { @Override public User2 call() throws Exception { System.out.println("exec call>>>return result"); return new User(500, "world"); } }); } }
package org.rui.test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFutureTask; /** * 刷新和回收不太一样。正如LoadingCache.refresh(K)所声明,刷新表示为键加载新值,这个过程可以是异步的。在刷新操作进行时, * 缓存仍然可以向其他线程返回旧值,而不像回收操作,读缓存的线程必须等待新值加载完成。 * * 如果刷新过程抛出异常,缓存将保留旧值,而异常会在记录到日志后被丢弃 * * @author lenovo * */ public class Refresh { static int ixs = 0; public static void main(String[] args) throws InterruptedException, ExecutionException { LoadingCache<String, String> graphs = CacheBuilder.newBuilder() .maximumSize(1000).refreshAfterWrite(1, TimeUnit.MICROSECONDS) .build(new CacheLoader<String, String>() { @Override public ListenableFuture<String> reload(final String key, String oldValue) throws Exception { System.out.println("oldValue:" + oldValue); ixs++; if (key.equals("keyx")) { return Futures.immediateFuture("new Values_" + ixs); } else { ListenableFutureTask<String> taks = ListenableFutureTask .create(new Callable<String>() { @Override public String call() throws Exception { return key + " xxxxxx_" + ixs; } }); Executor executor = new ExecutorImple(); executor.execute(taks); return taks; } } @Override public String load(String arg0) throws Exception { return "get-if-absent-compute_" + ixs; } }); String resultVal = null; resultVal = graphs.get("key"); System.out.println(resultVal); Thread.sleep(2000); resultVal = graphs.get("key"); System.out.println(resultVal); Thread.sleep(2000); resultVal = graphs.get("key"); System.out.println(resultVal); Thread.sleep(5000); resultVal = graphs.get("key"); System.out.println(resultVal); } }
package org.rui.test; import java.util.Iterator; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import org.junit.Test; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheStats; /** * 统计 信息 * * @author lenovo * */ public class RecordStatus { Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(2) .recordStats().build(); @Test public void loadCached() throws ExecutionException { String result = cache.get("key", new Callable<String>() { public String call() { return "result"; } }); String result2 = cache.get("key2", new Callable<String>() { public String call() { return "result2"; } }); String result3 = cache.get("key3", new Callable<String>() { public String call() { return "result3"; } }); result = cache.get("key", new Callable<String>() { public String call() { return "result"; } }); System.out.println(result); System.out.println(result2); System.out.println(result3); System.out.println(cache.getIfPresent("key")); // CacheStats cstats = cache.stats(); System.out.println("loadCount:" + cstats.loadCount() + " loadSuccessCount: " + cstats.loadSuccessCount()); System.out.println("缓存命中率:" + cstats.hitRate() + " hitCount: " + cstats.hitCount());// 缓存命中率; System.out.println("加载新值的平均时间:" + cstats.averageLoadPenalty() + " 纳秒");// 加载新值的平均时间,单位为纳秒; System.out.println("缓存项被回收的总数:" + cstats.evictionCount());// 缓存项被回收的总数,不包括显式清除。 System.out.println(); // cache.asMap().entrySet() Set<String> set = cache.asMap().keySet();// 所有健 Iterator<String> it = set.iterator(); System.out.println("all key===="); while (it.hasNext()) { System.out.print(it.next() + " \t "); } System.out.println(); } }
下面是本人自已的想法,还没正实可用性,仅参考
package org.rui.utils; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import com.google.common.cache.Cache; /** * guava cached 共公接口 * * @author liangrui * @date 2015/6/7 * @param <K> * @param <V> */ public interface ICached<K, V> { /** * callable 获取cached 方式 * * @param key * @param callable * @return * @throws ExecutionException */ V getCallable(K key, Callable<V> callable) throws ExecutionException; /** * cachedLoader 获取方式 * * @param key * @return * @throws ExecutionException */ V getLoader(K key) throws ExecutionException; /** * 获取某一项的 缓存 * * @param Cached * @return */ Cache getCache(String Cached); /** * 获取所有guava 缓存 * * @return */ Cache[] getCache(); }
package org.rui.utils; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; /** * 方便统一管理缓存 关于配置可根据系统实际情况配置 * * @date 2015/6/7 * @author liangrui * */ public class GuavaCachedImpl implements ICached<String, Object> { /*** cached 缓存最大数量 **/ public static final Integer CACHE_MAXIMUMSIZE = 10000;// /** loaderCached 缓存最大数量 **/ public static final Integer LOADING_CACHE_MAXIMUMSIZE = 10000; /*** 缓存项在给定时间内没有被写访问(创建或覆盖),则回收 **/ public static final Integer EXPIRE_AFTER_WRITE_MILLISECONDS = 1000; private Cache<String, Object> cache = CacheBuilder .newBuilder() .maximumSize(CACHE_MAXIMUMSIZE) .expireAfterWrite(EXPIRE_AFTER_WRITE_MILLISECONDS, TimeUnit.MILLISECONDS).recordStats().build(); private LoadingCache<String, Object> loadingCached = CacheBuilder .newBuilder() .maximumSize(LOADING_CACHE_MAXIMUMSIZE) .expireAfterWrite(EXPIRE_AFTER_WRITE_MILLISECONDS, TimeUnit.MILLISECONDS) .build(new CacheLoader<String, Object>() { @Override public String load(String key) throws Exception { System.out.println("key:" + key); if ("key".equals(key)) { return "key return result"; } else { return "get-if-absent-compute"; } } }); @Override public Object getCallable(String key, Callable<Object> callable) throws ExecutionException { Object value = cache.get(key, callable); return value; } @Override public Object getLoader(String key) throws ExecutionException { return loadingCached.get(key); } @Override public Cache getCache(String cahced) { if ("cache".equals(cahced)) { return cache; } if ("loadingCached".equals(cahced)) { return loadingCached; } else { } return null; } @Override public Cache[] getCache() { Cache[] cacheArray = new Cache[] { cache, loadingCached }; return cacheArray; } }
package org.rui.utils; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import com.google.common.cache.Cache; import com.google.common.cache.CacheStats; /** * cache 测试 * * @author lenovo * */ public class Main { public static void main(String[] args) throws ExecutionException { ICached<String, Object> cached = new GuavaCachedImpl(); Object result = cached.getCallable("key1", new Callable<Object>() { @Override public Object call() throws Exception { return "|cached value|"; } }); System.out.println(cached.getLoader("key")); System.out.println(result); printStats(cached.getCache()); } /** * 打印缓存状态信息 * * @param caches */ public static void printStats(Cache[] caches) { System.out.println("打印缓存状态信息"); for (Cache cache : caches) { System.out.println(); System.out .println("start------------------------------------------> "); System.out.println("loadCount:" + cache.stats().loadCount() + " loadSsuccessCount: " + cache.stats().loadSuccessCount()); System.out.println("缓存命中率:" + cache.stats().hitRate() + " hitCount: " + cache.stats().hitCount());// 缓存命中率; System.out.println("加载新值的平均时间:" + cache.stats().averageLoadPenalty() + " 纳秒");// 加载新值的平均时间,单位为纳秒; System.out.println("缓存项被回收的总数:" + cache.stats().evictionCount());// 缓存项被回收的总数,不包括显式清除。 System.out.println(); System.out.println(); System.out.println("cached 健和值 ==============="); Set setEn = cache.asMap().entrySet(); Iterator<Object> it = setEn.iterator(); System.out.println(); System.out.println("all entrySet====>"); while (it.hasNext()) { System.out.print(it.next() + " \t "); } System.out.println(); System.out.println(); Set<String> set = cache.asMap().keySet();// 所有健 Iterator<String> it2 = set.iterator(); System.out.println("all key====>"); while (it2.hasNext()) { System.out.print(it2.next() + " \t "); } System.out.println(); System.out .println("end------------------------------------------> "); } } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。