Guava Cache与ConcurrentMap很类似基于分段锁及线程安全,但也不彻底同样。最基本的区别是ConcurrentMap会一直保存全部添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,一般都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是颇有用的,由于它会自动加载缓存。html
1)能够接受消耗内存来提升性能java
2)某些key会被屡次查询git
3)缓存中的数据量不会超出内存容量api
package com.guava.cache; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; 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.collect.Lists; /** * * @author gaojiayi * */ public class TestCache { //基于loadingCache加载 //@Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ //提供默认的加载加载方式,在实际生产中,能够选择从DB中,或者文件中加载相应的value @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } //批量加载 @Override public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception { // TODO Auto-generated method stub Map<String, String> retMap = new HashMap<String, String>(); for(String key: keys){ retMap.put(key, load(key)); } return retMap; } }); System.out.println("jerry value:"+cahceBuilder.apply("jerry")); //get(K)方法,这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地加载新值。 System.out.println("jerry value:"+cahceBuilder.get("jerry")); System.out.println("peida value:"+cahceBuilder.get("peida")); System.out.println("peida value:"+cahceBuilder.apply("peida")); System.out.println("lisa value:"+cahceBuilder.apply("lisa")); //使用cache.put(key, value)方法能够直接向缓存中插入值,这会直接覆盖掉给定键以前映射的值 cahceBuilder.put("harry", "ssdded"); System.out.println("harry value:"+cahceBuilder.get("harry")); System.out.println("________________________________________"); List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); System.out.println(cahceBuilder.getAll(list)); } //基于Callable加载 @Test public void testcallableCache()throws Exception{ Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build(); String resultVal = cache.get("jerry", new Callable<String>() { public String call() { String strProValue="hello "+"jerry"+"!"; return strProValue; } }); System.out.println("jerry value : " + resultVal); resultVal = cache.get("peida", new Callable<String>() { public String call() { String strProValue="hello "+"peida"+"!"; return strProValue; } }); System.out.println("peida value : " + resultVal); } }
使用CacheBuilder构建的缓存不会"自动"执行清理和回收工做,也不会在某个缓存项过时后立刻清理,也没有诸如此类的清理机制。相反,它会在写操做时顺带作少许的维护工做,或者偶尔在读操做时作——若是写操做实在太少的话。缓存
这样作的缘由在于:若是要自动地持续清理缓存,就必须有一个线程,这个线程会和用户操做竞争共享锁。此外,某些环境下线程建立可能受限制,这样CacheBuilder就不可用了。安全
相反,咱们把选择权交到你手里。若是你的缓存是高吞吐的,那就无需担忧缓存的维护和清理等工做。若是你的 缓存只会偶尔有写操做,而你又不想清理工做阻碍了读操做,那么能够建立本身的维护线程,以固定的时间间隔调用Cache.cleanUp()。ScheduledExecutorService能够帮助你很好地实现这样的定时调度。oracle
CacheBuilder.maximumSize(long)。app
//。在权重限定场景中,除了要注意回收也是在重量逼近限定值时就进行了, //还要知道重量是在缓存建立时计算的,所以要考虑重量计算的复杂度。 Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000) .maximumWeight(100) .weigher(new Weigher<String,String>(){ @Override public int weigh(String key, String value) { // TODO Auto-generated method stub return value.getBytes().length; } }).build();
经过使用弱引用的键、或弱引用的值、或软引用的值,Guava Cache能够把缓存设置为容许垃圾回收:异步
任什么时候候,你均可以显式地清除缓存项,而不是等到它被回收:ide
LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() //注意:缓存并不会由于刷新盲目地定时重置,若是缓存项没有被检索,那刷新就不会真的发生, //(能够理解未异步定时获取新增,而不会作刷新,只有被检索时才会真正刷新) //若是设置过时(expireAfterWrite)缓存项在过时时间后也变得能够回收。 .refreshAfterWrite(2, TimeUnit.MINUTES) .build(new CacheLoader<String, String>(){ //提供默认的加载加载方式,在实际生产中,能够选择从DB中,或者文件中加载相应的value @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } //从新加载:重载CacheLoader.reload(K, V)能够扩展刷新时的行为,这个方法容许开发者在计算新值时使用旧的值。 @Override public ListenableFuture<String> reload(String key, String oldValue) throws Exception { // TODO Auto-generated method stub return super.reload(key, oldValue); } });
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000) .removalListener(new RemovalListener<String,String>(){ @Override public void onRemoval(RemovalNotification<String, String> removalnotification) { // 释放资源 }})