Guava Cache本地缓存
Posted ken-jl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Guava Cache本地缓存相关的知识,希望对你有一定的参考价值。
Guava介绍
Guava是一种基于开源的Java库,其中包含谷歌正在由他们很多项目使用的很多核心库。
这个库是为了方便编码,并减少编码错误。
这个库提供用于集合,缓存,支持原语,并发性,常见注解,字符串处理,I/O和验证的实用方法。
Guava Cache适用场景
1 消耗一些内存空间来提升速度;
2 缓存中存放的数据总量不会超出内存容量。
(Guava Cache是单个应用运行时的本地缓存,不把数据存放到文件或外部服务器(Memcached, Redis))
Guava Cache介绍
数据结构:ConcurrentHash (The returned cache is implemented as a hash table with similar performance characteristics to ConcurrentHashMap
.)
主要特性(详见下面的相关链接):
1 自动加载
2 回收策略:
2.1 基于容量
2.2 基于存活时间
2.3 基于权重
2.4 基于引用
3 移除监听器
4 缓存访问统计
主要接口:CacheBuilder, LoadingCache, CacheStats
使用示例:
public class CacheProTest { LoadingCache<Long, Person> cache; private int cacheTimeoutSeconds = 10; // 10秒 Integer counter = 1; @Before public void initialize() { System.out.println("初始化"); cache = CacheBuilder.newBuilder() /* 回收策略:基于容量(least-recently-used eviction when a maximum size is exceeded) */ .maximumSize(10) // .initialCapacity(initialCapacity) /* 回收策略:基于存活时间(time-based expiration of entries, measured since last access or last write) */ .expireAfterWrite(cacheTimeoutSeconds, TimeUnit.SECONDS) // .expireAfterAccess(duration, unit) // .refreshAfterWrite(duration, unit) /* 回收策略:基于权重 */ // .maximumWeight(maximumWeight) // .weigher(weigher) /* 回收策略:基于引用(keys automatically wrapped in weak references, values automatically wrapped in weak or soft references)*/ // .weakKeys() // .weakValues() // .softValues() // 设置并发数为5,即同一时间最多只能有5个线程往cache执行写入操作 // .concurrencyLevel(concurrencyLevel) /* 缓存访问统计(accumulation of cache access statistics) */ .recordStats() /* 移除监听器(notification of evicted (or otherwise removed) entries) */ // .removalListener(listener) .build(new CacheLoader<Long, Person>() { /* 自动加载(automatic loading of entries into the cache) */ @Override public Person load(Long id) throws Exception { System.out.println("获取值, id=" + id); // 调用接口获取值 Person p = new Person(); p.setId(id); p.setName("name" + counter.toString()); counter++; return p; } }); } @Test public void test1() { try { /* 获值 */ // ConcurrentMap<Long, Person> asMap = cache.asMap(); // cache.get(key); // // cache.getAll(keys); // cache.getIfPresent(key); // cache.getAllPresent(keys); // cache.size(); /* 存值 */ // cache.put(key, value); // cache.putAll(m); // Map<? extends K, ? extends V> m /* 移除/删除 */ // cache.refresh(key); // cache.invalidate(key); // cache.invalidateAll(); // cache.invalidateAll(keys); // cache.cleanUp(); /* 缓存访问统计 */ CacheStats stats = cache.stats(); stats.averageLoadPenalty(); stats.evictionCount(); stats.hitCount(); stats.hitRate(); stats.loadCount(); stats.loadExceptionCount(); stats.loadExceptionRate(); stats.loadSuccessCount(); stats.missCount(); stats.missRate(); stats.requestCount(); stats.totalLoadTime(); } catch (Exception e) { e.printStackTrace(); } } @Test public void test2() { try { Long id = 1L; Person person1 = cache.get(id); Thread.sleep(3L * 1000L); Person person2 = cache.get(id); Thread.sleep(11L * 1000L); Person person3 = cache.get(id); System.out.println(person1); System.out.println(person2); System.out.println(person3); } catch (Exception e) { e.printStackTrace(); } } } class Person implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return JSON.toJSONString(this); } }
Guava Cache使用时需要关注的点
1 了解LoadingCache.refresh
正如LoadingCache.refresh(K)所声明,刷新表示为键加载新值,这个过程可以是异步的。
在刷新操作进行时,缓存仍然可以向其他线程返回旧值,而不像回收操作,读缓存的线程必须等待新值加载完成。
如果刷新过程抛出异常,缓存将保留旧值,而异常会在记录到日志后被丢弃[swallowed]。
重载CacheLoader.reload(K, V)可以扩展刷新时的行为,这个方法允许开发者在计算新值时使用旧的值。
2 了解 清理时机
使用CacheBuilder构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没有诸如此类的清理机制。
它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做——如果写操作实在太少的话。
因此使用LoadingCache.size() 一定要关注这个点。
相关链接
以上是关于Guava Cache本地缓存的主要内容,如果未能解决你的问题,请参考以下文章