Guava缓存
Guava缓存是Google Guava库中提供的一种缓存实现,可以帮助我们在应用程序中轻松实现缓存功能。Guava缓存提供了一些高级功能,例如自动加载、过期时间、最大缓存大小、缓存回收等。
CacheBuilder跟Guava缓存的关系
CacheBuilder是Guava缓存的构建器,提供了一些方法来配置缓存的行为,例如设置缓存的最大大小、过期时间、缓存回收策略等。通过CacheBuilder,可以创建一个Guava缓存实例。
即CacheBuilder是Guava缓存的一部分,提供了一种方便的方式来创建和配置Guava缓存实例。
CacheBuilder类的常用方法
maximumSize(int size)
作用:设置缓存的最大容量,当超过这个容量的时候,最近最少使用的条目会被回收。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.build();
maximumWeight(long weight)
作用:设置缓存的最大重量,当超过这个重量的时候,最近最少使用的条目会被回收。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumWeight(1000)
.build();
expireAfterAccess(long duration, TimeUnit unit)
作用:在指定时间内没有被读/写访问,则回收缓存条目。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build();
expireAfterWrite(long duration, TimeUnit unit)
作用:在指定时间内没有被写访问,则回收缓存条目。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
refreshAfterWrite(long duration, TimeUnit unit)
作用:设置缓存项在写入一定时间后自动刷新。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(10, TimeUnit.MINUTES)
.build();
initialCapacity(int capacity)
作用:设置缓存的初始容量,用于控制缓存的内存分配。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.initialCapacity(100)
.build();
recordStats()
作用:启用缓存统计信息,可以获取缓存的命中率、平均加载时间等指标。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.recordStats()
.build();
build()
作用:构建缓存实例。
java
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.build();
build方法用于构建一个缓存对象。接受一个CacheLoader对象作为参数,用于定义缓存的加载逻辑。CacheLoader是一个抽象类,需要实现load方法来定义如何加载缓存数据。
build方法定义:
java
public <K, V> Cache<K, V> build(CacheLoader<? super K, V> loader)
该方法返回一个Cache对象,该对象可以用于存储和获取缓存数据
示例代码:
java
public void test() {
// 创建一个Cache对象
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(100) // 设置缓存的最大容量
.expireAfterWrite(10, TimeUnit.MINUTES) // 设置缓存项的过期时间
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
// 在缓存中没有找到对应值时,自动加载该值
return "value for " + key;
}
});
try {
// 获取缓存数据
String value = cache.get("key");
System.out.println(value); // 输出:Value for key
// 缓存中不存在该数据时,会调用CacheLoader的load方法加载数据
String value2 = cache.get("key2");
System.out.println(value2); // 输出:Value for key2
} catch (ExecutionException e) {
e.printStackTrace();
}
}
创建了一个最大容量为100,写入后10分钟过期的缓存实例,并使用CacheLoader自动加载缓存值。当缓存中没有找到对应值时,CacheLoader的load方法会被调用,返回对应的值。
CacheLoader类
CacheLoader类是Guava缓存库中的一个重要类,用于定义缓存加载的逻辑。
CacheLoader类的常用方法
load(K key)
作用:加载指定键的缓存值。如果缓存中不存在该键的值,则通过该方法加载并返回
- 当缓存中不存在指定键的值时,会调用该方法。
- 该方法用于从数据源或其他方式获取缓存的值。
loadAll(Iterable<? extends K> keys)
作用:批量加载指定键集合的缓存值。如果缓存中不存在某个键的值,则通过该方法加载
java
acheLoader<String, String> cacheLoader = new CacheLoader<String, String>() {
@Override
public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
Map<String, String> values = new HashMap<>();
for (String key : keys) {
// 从数据库或其他数据源加载缓存值的逻辑
values.put(key, "Value for " + key);
}
return values;
}
};
List<String> keys = Arrays.asList("key1", "key2", "key3");
Map<String, String> values = cacheLoader.loadAll(keys);
System.out.println(values); // Output: {key1=Value for key1, key2=Value for key2, key3=Value for key3}
reload(K key, V oldValue)
作用:重新加载指定键的缓存值。该方法在缓存值过期或被移除时调用,用于更新缓存值
- 当缓存中的键值对需要被刷新或重新加载时,会调用该方法。
- 该方法在缓存中存在旧值的情况下被调用,用于获取新值并替换旧值。
- 通常在缓存的刷新策略中使用,例如定时刷新或手动刷新。
java
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class MyCacheLoader<K, V> extends CacheLoader<K, V> {
private Executor executor = Executors.newSingleThreadExecutor();
@Override
public V load(K key) throws Exception {
// 在这里实现加载缓存的逻辑
// 返回缓存值
return null;
}
@Override
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
SettableFuture<V> future = SettableFuture.create();
executor.execute(() -> {
try {
// 在这里实现重新加载缓存的逻辑
// 将重新加载的缓存值设置到future中
V newValue = null;
future.set(newValue);
} catch (Exception e) {
// 如果重新加载缓存失败,设置异常到future中
future.setException(e);
}
});
return future;
}
}
创建了一个自定义的CacheLoader类,继承自CacheLoader<K, V>。在load方法中,你可以实现加载缓存的逻辑,并返回缓存值。
在reload方法中,使用了ListenableFuture来表示重新加载缓存的异步操作。创建了一个SettableFuture对象,用于保存重新加载的缓存值。然后,使用一个Executor来执行重新加载缓存的逻辑,将重新加载的缓存值设置到future中。如果重新加载缓存失败,我们将异常设置到future中。
这样,就可以在CacheLoader类中使用reload方法来实现缓存的重新加载操作了。
Guava线程池
Guava的线程池主要包含以下几个类:
-
ListeningExecutorService:一个可监听的ExecutorService,可以在任务执行完成时触发回调函数。
-
MoreExecutors:提供了一些常用的ExecutorService的工厂方法,例如newDirectExecutorService()、newFixedThreadPool()、newCachedThreadPool()等。
-
ThreadFactoryBuilder:一个用于创建线程工厂的Builder类,可以设置线程名、优先级、是否为守护线程等属性。
java
import com.google.common.util.concurrent.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
public class GuavaThreadPoolDemo {
public static void main(String[] args) throws Exception {
// 创建线程池
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
Executors.newFixedThreadPool(10, new ThreadFactoryBuilder()
.setNameFormat("guava-pool-%d")
.setDaemon(true)
.build()));
// 提交任务
ListenableFuture<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
// 模拟耗时操作
Thread.sleep(1000);
return "Hello, Guava!";
}
});
// 添加回调函数
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println(result);
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
}, executorService);
// 关闭线程池
executorService.shutdown();
}
}
使用MoreExecutors工厂方法创建了一个固定大小的线程池,然后使用ListeningExecutorService包装它,使其可以监听任务执行完成事件。接着,提交了一个Callable任务,并使用Futures.addCallback方法添加了一个回调函数,当任务执行完成时会自动触发回调函数。最后,关闭了线程池。
Guava的线程池和Guava缓存的结合示例代码
java
import com.google.common.cache.CacheLoader;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class MyCacheLoader<K, V> extends CacheLoader<K, V> {
// 创建线程池
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
Executors.newFixedThreadPool(10, new ThreadFactoryBuilder()
.setNameFormat("guava-pool-%d")
.setDaemon(true)
.build()));
@Override
public V load(K key) throws Exception {
// 在这里实现加载缓存的逻辑
// 返回缓存值
return null;
}
@Override
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
SettableFuture<V> future = SettableFuture.create();
executorService.execute(() -> {
try {
// 在这里实现重新加载缓存的逻辑
// 将重新加载的缓存值设置到future中
V newValue = null;
future.set(newValue);
} catch (Exception e) {
// 如果重新加载缓存失败,设置异常到future中
future.setException(e);
}
});
return future;
}
}