【拉勾GuavaCache-2】高级应用
文章内容输出来源:拉勾教育Java高薪训练营
希望记录的每一个点,都能真正掌握,而不是流水账
上一篇讲解了基本使用,这一篇来看一些高级知识点
一:并发设置
使用concurrencyLevel属性设置并发线程数,该值就是segment数组长度,如ConcurrentHashMap一般,数组多长就支持多少个并发。
LoadingCache<String,Object> cache = CacheBuilder.newBuilder()// 最大3个 同时支持CPU核数线程写缓存.maximumSize(3).concurrencyLevel(Runtime.getRuntime().availableProcessors()).build();
V get(K key, CacheLoader<? super K, V> loader) throws ExecutionException {int hash = this.hash(Preconditions.checkNotNull(key));//通过hash值确定该key位于哪一个segment上,并获取该segmentreturn this.segmentFor(hash).get(key, hash, loader);}
二:更新锁定
如下,refreshAfterWrite指定,在3s内没有写操作更新,则回源查询新值,没有则返回旧值。 关键在于,回源只会有一个请求,其他请求会阻塞等待,避免缓存穿透造成雪崩。
LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
// 最大3个 同时支持CPU核数线程写缓存.maximumSize(3).concurrencyLevel(Runtime.getRuntime().availableProcessors()).//3秒内阻塞会返回旧数据refreshAfterWrite(3,TimeUnit.SECONDS).build();
三:疑难问题:
1、会发生oom吗 (内存溢出)?
会发生。 所以我们要注意设置缓存过期,数量的设置也要考虑实际内存大小。 另外,可以使用弱引用方式缓存对象,这样可以及时被回收。Cache<String, String> cache = CacheBuilder.newBuilder() .expireAfterWrite(1, TimeUnit.SECONDS).weakValues().build();
2、缓存到期就会立即被清除吗?
不是的。 是在每次操作缓存时候,如读取或更新时判断是否过期,主动删除。
3、如何找出最久未使用的数据?
使用访问队列,该队列会把新访问的数据放到队列末尾,在队首的就是最久的。那么,对于最久未更新的,就可以使用写队列了。