Guava(十)

13 篇文章 0 订阅

目录

【缓存】
    缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管 LoadingCache不回收元素,它也是很有用的,因为它会自动加载缓存。

通常来说,Guava Cache适用于:
● 你愿意消耗一些内存空间来提升速度。
● 你预料到某些键会被查询一次以上。
● 缓存中存放的数据总量不会超出内存容量。
但注意:Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。

private static void CacheTest() throws Exception {
	LoadingCache<Integer, Goods> cache = CacheBuilder.newBuilder()
		.concurrencyLevel(2)  // 设置并发级别,并发级别是指可以同时写缓存的线程数
		.expireAfterWrite(10, TimeUnit.MINUTES)  // 设置写缓存后过期时间
		.expireAfterAccess(10, TimeUnit.SECONDS) // 设置访问后的过期时间
		.refreshAfterWrite(10, TimeUnit.SECONDS) // 设置缓存定时刷新时间
		.recordStats()        // 设置要统计缓存的命中率,通过 status()方法查看
		.initialCapacity(10)  // 设置缓存容器的初始容量
		.weakKeys()           // 设置弱引用存储键
//		.maximumSize(100)     // 设置缓存最大容量为,超过最大容量 按照LRU最近最少使用算法来移除缓存项
		.maximumWeight(100)   // 设置最大权重
		.weigher(new Weigher<Object, Object>() {  // 设置权重函数
			@Override
			public int weigh(Object key, Object value) {
				return 100;
			}
		})
		.removalListener(new RemovalListener<Object, Object>() {   //设置缓存的移除通知
			@Override
			public void onRemoval(RemovalNotification<Object, Object> notification) {
				System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
			}
		})
		.build(
				new CacheLoader<Integer, Goods>() {
					@Override
					public Goods load(Integer key) throws Exception {
						System.out.println("load goods " + key);
						return new Goods(key, "name" + key);
					}
				}
		);

	for (int i = 0; i < 20; i++) {
		System.out.println(cache.get(1));
		TimeUnit.SECONDS.sleep(1);
	}

	System.out.println("cache status: " + cache.stats().toString());
	System.out.println("cache map: " + cache.asMap()); // 返回 ConcurrentMap
}

static class Goods {
	private int id;
	private String name;

	public Goods(int id, String name) {
		this.id = id;
		this.name = name;
	}

	@Override
	public String toString() {
		return "Students{id=" + id + ", name='" + name + "'}";
	}
}

一、加载
● LoadingCache通过 CacheBuilder创建,只需要实现 load(K key) throws Exception 方法即可自定义缓存。

● 取缓存的通用方法是 get(K)。若缓存不存在,则 CacheLoader会向缓存原子性的加载新值。
如果 CacheLoader没有定义异常,可以通过 getUnchecked(K)查找;但如果声明了异常,就不能使用 getUnchecked(K)。

● getAll(Iterable<? extends K>)方法用来执行批量查询。默认情况下,对每个不存在的缓存都会单独的去调用 load(K)方法。另外,如果批量加载会更高效,可使用 loadAll()方法。

● 使用 put(key, value)方法可以直接向缓存插入值,并且直接覆盖掉给定键之前映射的值。

二、回收
Guava Cache提供了三种基本的缓存回收方式:基于容量回收、定时回收和基于引用回收

1.基于容量的回收

--
CacheBuilder.maximumSize(long)缓存将尝试回收最近没有使用或总体上很少使用的缓存项(发生在缓存项数目逼近限定值时)
CacheBuilder.weigher(Weigher)指定一个权重函数,并用 maximumWeight(long)指定最大总重

2.定时回收

--
expireAfterAccess(long, TimeUnit)缓存项在给定时间内没有被读/写访问,则回收
expireAfterWrite(long, TimeUnit)缓存项在给定时间内没有被写访问,则回收

3.基于引用的回收

--
CacheBuilder.weakKeys()使用弱引用存储键。当键没有其它(强或软)引用时,缓存项可以被垃圾回收
CacheBuilder.weakValues()使用弱引用存储值。当值没有其它(强或软)引用时,缓存项可以被垃圾回收
CacheBuilder.softValues()使用软引用存储值。软引用只有在响应内存需要时,才按照全局最近最少使用的顺序回收

4.显示清除

--
invalidate(key)单个清除
invalidateAll(keys)批量清除
invalidateAll()全部清除

5.移除监听器

--
CacheBuilder.removalListener(RemovalListener)当缓存项被移除时做一些额外操作。

6.刷新

--
refresh(K)刷新,为键加载新值,这个过程可以是异步的
CacheBuilder.refreshAfterWrite()自动定时刷新

三、其他
1.统计
CacheBuilder.recordStats()用于设置缓存的统计功能,通过 status()方法返回统计信息:
● hitRate(): 缓存命中率
● averageLoadPenalty():加载平均时间(ns)
● evictionCount():缓存项被回收的总数,不包括显示清除
● totalLoadTime(): 总加载时间

2.asMap视图
asMap视图提供了缓存的ConcurrentMap形式


关于guava cache的详细解读可以参考:
https://mp.weixin.qq.com/s/vi8Y-u-uZc6V357yqwVH1g

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值