Caching ist eine wesentliche Methode zur Lösung von Leistungsproblemen in unserer täglichen Entwicklung. Einfach ausgedrückt ist Cache ein Speicherplatz, der zur Verbesserung der Systemleistung freigeschaltet wird.
Caching wird häufig in vielen Systemen und Architekturen verwendet, wie zum Beispiel:
1. CPU-Cache
2. Betriebssystem-Cache
3. Lokaler Cache
4. Verteilter Cache
5. HTTP-Cache
6. Datenbank-Cache
Warten Sie, das kann man im Bereich Computer und Netzwerke sagen , Caching ist überall. Man kann sagen, dass bei ungleicher Hardwareleistung überall dort Cache vorhanden ist, wo es um die Netzwerkübertragung geht.
Guava Cache ist eine lokale Cache-Implementierung mit vollem Speicher, die einen Thread-sicheren Implementierungsmechanismus bietet. Insgesamt ist der Guava-Cache die beste Wahl für lokales Caching. Er ist einfach zu verwenden und bietet eine gute Leistung.
Es gibt zwei Möglichkeiten, einen Guava-Cache zu erstellen:
1. CacheLoader
2. aufrufbarer Rückruf
Der mit diesen beiden Methoden erstellte Cache ist derselbe Wie üblich besteht der Unterschied zwischen der Verwendung von Map to Cache darin, dass beide Methoden eine Logik implementieren: Nehmen Sie den Wert von Schlüssel um diesen Wert zu erhalten. Der Unterschied besteht jedoch darin, dass die Definition des Cacheloaders relativ weit gefasst ist und für den gesamten Cache definiert wird. Dies kann als einheitliche Methode zum Laden von Werten basierend auf dem Schlüsselwert angesehen werden. Die aufrufbare Methode ist flexibler und ermöglicht es Ihnen, ein Beispiel für die Implementierung der CacheLoader-Methode anzugeben, wenn Sie Folgendes erhalten:
[code] @Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } }); System.out.println("jerry value:"+cahceBuilder.apply("jerry")); 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")); cahceBuilder.put("harry", "ssdded"); System.out.println("harry value:"+cahceBuilder.get("harry")); }
[code] @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); } 输出: jerry value : hello jerry! peida value : hello peida!
Wiederverwendete Parameter:
1. Größeneinstellung: CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)
2 (long, TimeUnit) ExpireAfterWrite(long, TimeUnit)
3. Referenz: CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()
4. Explizites Löschen: invalidate(key ) invalidateAll(keys) invalidateAll()
5. Listener löschen: CacheBuilder.removalListener(RemovalListener)
Aktualisierungsmechanismus:
1. LoadingCache. fresh(K) Beim Generieren eines neuen Werts wird weiterhin der alte Wert verwendet.
2. CacheLoader.reload(K, V) ermöglicht die Verwendung alter Werte beim Generieren neuer Werte
3. CacheBuilder.refreshAfterWrite(long, TimeUnit) automatisch aktualisiert den Cache
[code] /** * 不需要延迟处理(泛型的方式封装) * @return */ public <K , V> LoadingCache<K , V> cached(CacheLoader<K , V> cacheLoader) { LoadingCache<K , V> cache = CacheBuilder .newBuilder() .maximumSize(2) .weakKeys() .softValues() .refreshAfterWrite(120, TimeUnit.SECONDS) .expireAfterWrite(10, TimeUnit.MINUTES) .removalListener(new RemovalListener<K, V>(){ @Override public void onRemoval(RemovalNotification<K, V> rn) { System.out.println(rn.getKey()+"被移除"); }}) .build(cacheLoader); return cache; } /** * 通过key获取value * 调用方式 commonCache.get(key) ; return String * @param key * @return * @throws Exception */ public LoadingCache<String , String> commonCache(final String key) throws Exception{ LoadingCache<String , String> commonCache= cached(new CacheLoader<String , String>(){ @Override public String load(String key) throws Exception { return "hello "+key+"!"; } }); return commonCache; } @Test public void testCache() throws Exception{ LoadingCache<String , String> commonCache=commonCache("peida"); System.out.println("peida:"+commonCache.get("peida")); commonCache.apply("harry"); System.out.println("harry:"+commonCache.get("harry")); commonCache.apply("lisa"); System.out.println("lisa:"+commonCache.get("lisa")); } peida:hello peida! harry:hello harry! peida被移除 lisa:hello lisa!
[code]private static Cache<String, String> cacheFormCallable = null; /** * 对需要延迟处理的可以采用这个机制;(泛型的方式封装) * @param <K> * @param <V> * @param key * @param callable * @return V * @throws Exception */ public static <K,V> Cache<K , V> callableCached() throws Exception { Cache<K, V> cache = CacheBuilder .newBuilder() .maximumSize(10000) .expireAfterWrite(10, TimeUnit.MINUTES) .build(); return cache; } private String getCallableCache(final String userName) { try { //Callable只有在缓存值不存在时,才会调用 return cacheFormCallable.get(userName, new Callable<String>() { @Override public String call() throws Exception { System.out.println(userName+" from db"); return "hello "+userName+"!"; } }); } catch (ExecutionException e) { e.printStackTrace(); return null; } } @Test public void testCallableCache() throws Exception{ final String u1name = "peida"; final String u2name = "jerry"; final String u3name = "lisa"; cacheFormCallable=callableCached(); System.out.println("peida:"+getCallableCache(u1name)); System.out.println("jerry:"+getCallableCache(u2name)); System.out.println("lisa:"+getCallableCache(u3name)); System.out.println("peida:"+getCallableCache(u1name)); } 输出: peida from db peida:hello peida! jerry from db jerry:hello jerry! lisa from db lisa:hello lisa! peida:hello peida!
说明:Callable只有在缓存值不存在时,才会调用,比如第二次调用getCallableCache(u1name)直接返回缓存中的值
guava Cache数据移除:
guava做cache时候数据的移除方式,在guava中数据的移除分为被动移除和主动移除两种。
被动移除数据的方式,guava默认提供了三种方式:
1.基于大小的移除:看字面意思就知道就是按照缓存的大小来移除,如果即将到达指定的大小,那就会把不常用的键值对从cache中移除。
定义的方式一般为 CacheBuilder.maximumSize(long),还有一种一种可以算权重的方法,个人认为实际使用中不太用到。就这个常用的来看有几个注意点,
其一,这个size指的是cache中的条目数,不是内存大小或是其他;
其二,并不是完全到了指定的size系统才开始移除不常用的数据的,而是接近这个size的时候系统就会开始做移除的动作;
其三,如果一个键值对已经从缓存中被移除了,你再次请求访问的时候,如果cachebuild是使用cacheloader方式的,那依然还是会从cacheloader中再取一次值,如果这样还没有,就会抛出异常
2.基于时间的移除:guava提供了两个基于时间移除的方法
expireAfterAccess(long, TimeUnit) 这个方法是根据某个键值对最后一次访问之后多少时间后移除
expireAfterWrite(long, TimeUnit) 这个方法是根据某个键值对被创建或值被替换后多少时间移除
3.基于引用的移除:
这种移除方式主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除
主动移除数据方式,主动移除有三种方法:
1.单独移除用 Cache.invalidate(key)
2.批量移除用 Cache.invalidateAll(keys)
3.移除所有用 Cache.invalidateAll()
如果需要在移除数据的时候有所动作还可以定义Removal Listener,但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)
以上就是Java-类库-Guava-cache的内容,更多相关内容请关注PHP中文网(www.php.cn)!