关于介绍请参考: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------------------------------------------> ");
- }
- }
- }