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