guava cache使用例子

来源:互联网 发布:外国人评论中国知乎 编辑:程序博客网 时间:2024/05/22 01:43

关于介绍请参考: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 */@Testpublic void loadingCache(){LoadingCache<String, String> graphs = CacheBuilder.newBuilder().maximumSize(1000).build(new CacheLoader<String, String>(){@Overridepublic 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方法直接插入,但自动加载是首选的,因为它可以更容易地推断所有缓存内容的一致性。 */@Testpublic 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 */@Testpublic 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)指定一个权重函数 *  */@Testpublic void callablex() throws ExecutionException, InterruptedException{// .maximumSize(100)Cache<String, User2> cache = CacheBuilder.newBuilder().maximumWeight(5).weigher(new Weigher<String, User2>(){@Overridepublic int weigh(String arg0, User2 user){return 3;}}).removalListener(new RemovalListener<String, User2>(){@Overridepublic 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>(){@Overridepublic void onRemoval(RemovalNotification<String, User2> rn){System.out.println("Cause:" + rn.getCause() + " k: "+ rn.getKey() + " v :" + rn.getValue() + "==被移除");}}).build();@Testpublic void timerEvication() throws ExecutionException,InterruptedException{User2 user = cache2.get("k1", new Callable<User2>(){@Overridepublic 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>(){@Overridepublic User2 call() throws Exception{return new User(200, "hello2");}});System.out.println(user);Thread.sleep(8000);user = cache2.get("k1", new Callable<User2>(){@Overridepublic User2 call() throws Exception{return new User(10000000, "k1k1k1k1k1k1k1");}});System.out.println(cache2.size());User2 user3 = cache2.get("k3", new Callable<User2>(){@Overridepublic 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>(){@Overridepublic void onRemoval(RemovalNotification<String, User2> rn){System.out.println("Cause:" + rn.getCause() + " k: "+ rn.getKey() + " v :" + rn.getValue() + "==被移除");}}).build();@Testpublic void clear() throws ExecutionException{User2 u = cache3.get("u1", new Callable<User2>(){@Overridepublic 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>(){@Overridepublic 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>(){@Overridepublic 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>(){@Overridepublic 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>(){@Overridepublic String call() throws Exception{return key + " xxxxxx_" + ixs;}});Executor executor = new ExecutorImple();executor.execute(taks);return taks;}}@Overridepublic 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();@Testpublic 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>(){@Overridepublic 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";}}});@Overridepublic Object getCallable(String key, Callable<Object> callable)throws ExecutionException{Object value = cache.get(key, callable);return value;}@Overridepublic Object getLoader(String key) throws ExecutionException{return loadingCached.get(key);}@Overridepublic Cache getCache(String cahced){if ("cache".equals(cahced)) {return cache;}if ("loadingCached".equals(cahced)) {return loadingCached;} else {}return null;}@Overridepublic 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>(){@Overridepublic 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------------------------------------------> ");}}}


1 0
原创粉丝点击