La mise en cache est une méthode essentielle pour résoudre les problèmes de performances dans notre développement quotidien. En termes simples, le cache est un espace mémoire ouvert pour améliorer les performances du système.
La mise en cache est largement utilisée dans de nombreux systèmes et architectures, tels que :
1. Cache CPU
2. Cache du système d'exploitation
3. Cache local
4. Cache distribué
5. Cache HTTP
6. Cache de base de données
Attendez, on peut dire que dans le domaine des ordinateurs et des réseaux , La mise en cache est partout. On peut dire que tant que les performances matérielles seront inégales, le cache sera présent partout où la transmission réseau est impliquée.
Guava Cache est une implémentation de cache local pleine mémoire qui fournit un mécanisme d'implémentation thread-safe. Dans l’ensemble, le cache Guava est le meilleur choix pour la mise en cache locale. Il est facile à utiliser et offre de bonnes performances.
Il existe deux façons de créer un cache Guava :
1. cacheLoader
2. rappel appelable
Le cache créé par ces deux méthodes est le même comme d'habitude La différence entre utiliser map to cache est que les deux méthodes implémentent une logique - obtenir la valeur de la clé X du cache, si la valeur a été mise en cache, renvoyer la valeur dans le cache, si elle n'est pas mise en cache. Cependant, il existe une méthode pour obtenir cette valeur. Mais la différence est que la définition de cacheloader est relativement large et est définie pour l'ensemble du cache. Elle peut être considérée comme une méthode unifiée de chargement de valeur basée sur la valeur de la clé. La méthode appelable est plus flexible, vous permettant de spécifier
exemple d'implémentation de la méthode cacheLoader lors de l'obtention de :
[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")); }
implémentation du rappel appelable :
[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!
cache Description du paramètre :
Paramètres recyclés :
1. Paramètre de taille : CacheBuilder.maximumSize(long) CacheBuilder.weigher(Weigher) CacheBuilder.maxumumWeigher(long)
2 . (long, TimeUnit) expireAfterWrite(long, TimeUnit)
3. Référence : CacheBuilder.weakKeys() CacheBuilder.weakValues() CacheBuilder.softValues()
4. Suppression explicite : invalidate(key ) invalidateAll(keys) invalidateAll()
5. Supprimer l'écouteur : CacheBuilder.removalListener(RemovalListener)
Mécanisme d'actualisation :
1. LoadingCache. rafraîchir(K) Lors de la génération d'une nouvelle valeur, l'ancienne valeur sera toujours utilisée.
2. CacheLoader.reload(K, V) permet d'utiliser d'anciennes valeurs dans le processus de génération de nouvelles valeurs
3. CacheBuilder.refreshAfterWrite(long, TimeUnit) automatiquement actualise le 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!
Implémentation du Callable Cache générique :
[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)!