Guava之Supplier缓存使用示例

「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」。

使用guava作内存缓存,大多数小伙伴应该都使用过,通过CacheBuilder创建LoadingCache一个kv格式的缓存,如果我们需要缓存的只是一个value呢?

针对这种场景,接下来介绍一种基于Supplier来实现的缓存方式

1. Supplier使用姿势

guava的Supplier与jdk的Supplier从接口定义上来看没什么区别,对外只提供了一个get()方法

1
2
3
4
5
6
java复制代码@FunctionalInterface
@GwtCompatible
public interface Supplier<T> extends java.util.function.Supplier<T> {
@CanIgnoreReturnValue
T get();
}

重点需要关注的是Supplier创建的姿势,借助Suppliers来实现

下面是几个常见的创建姿势:

  • memoize: delegate为具体的获取值的委托类,需要注意的是,delegate的具体实现只会在首次时调用;这种方式相当于持久缓存
  • memoizeWithExpiration:delegate的返回值,会缓存一段时间;缓存时间过后,会重新调用一下delegate来获取返回值
  • ofInstance: 直接传参
1
2
3
4
5
java复制代码public static <T> Supplier<T> memoize(Supplier<T> delegate)

public static <T> Supplier<T> memoizeWithExpiration(Supplier<T> delegate, long duration, TimeUnit unit)

public static <T> Supplier<T> ofInstance(@Nullable T instance)

基于上面的方法描述,如果我们想实现一个10s缓存,那么可以选择memoizeWithExpiration来实现

1
2
3
4
5
6
7
java复制代码AtomicInteger atomicInteger = new AtomicInteger(1);
Supplier<Integer> cache = Suppliers.memoizeWithExpiration(this::ret, 10, TimeUnit.SECONDS);

private int ret() {
System.out.println("------- 更新 value --------");
return atomicInteger.getAndAdd(2) ;
}

上面定义了一个内存缓存cache, 缓存10s,调用时若缓存失效,会重新调用ret()刷新缓存

测试case就比较简单了

1
2
3
4
5
6
7
8
9
java复制代码@Test
public void testSupplier() throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.print(cache.get() + " | ");
}
System.out.println();
Thread.sleep(10000);
System.out.println(cache.get());
}

输出如下

1
2
3
4
diff复制代码------- 更新 value --------
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
------- 更新 value --------
3

2. 缓存刷新

使用Supplier当缓存时,需要注意的一点就是没有缓存失效的方法可供调用;对于LoadingCache若是想失效缓存,可以通过调用 invalidate来主动失效指定的缓存,那么Supplier 可以怎么整?

  • 直接重新赋值

比如当我们希望刷新时,可以直接覆盖就的supplier即可

1
2
3
java复制代码public void refresh() {
cache = Suppliers.memoizeWithExpiration(this::ret, 10, TimeUnit.SECONDS);
}

一灰灰的联系方式

尽信书则不如无书,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%