如何将条目填充到加载缓存番石榴中?
How to populate entries into Loading Cache guava?
我有一个用例,我想从多个线程将条目填充到数据结构中,并在达到特定大小后开始删除旧记录。所以我决定为此使用 Guava Loading Cache。
我想从多个线程将条目填充到我的加载缓存中,我将基于逐出的策略设置为 Size Based Eviction
。
private final ScheduledExecutorService executorService = Executors
.newSingleThreadScheduledExecutor();
private final LoadingCache<String, DataBuilder> cache =
CacheBuilder.newBuilder().maximumSize(10000000)
.removalListener(RemovalListeners.asynchronous(new CustomListener(), executorService))
.build(new CacheLoader<String, DataBuilder>() {
@Override
public DataBuilder load(String key) throws Exception {
// what I should do here?
// return
}
});
// this will be called from multiple threads to populate the cache
public void addToCache(String key, DataBuilder dataBuilder) {
// what I should do here?
//cache.get(key).
}
我的 addToCache
方法将从多个线程调用以填充 cache
。我很困惑我应该在 addToCache
方法中做什么来填充缓存以及我的 load
方法是什么样的?
这里 DataBuilder
是我的构建器模式。
显然你的问题是你没有得到 CacheLoader
的主要目的。
A CacheLoader
用于在调用 get(K key)
or getUnchecked(K key)
时自动加载给定键(缓存中尚不存在)的值,即使我们有多个线程尝试要同时获取同一个键的值,实际上只有一个线程会加载该值,一旦完成,所有调用线程都将具有相同的值。
当加载值需要一些时间时,这通常很有用,例如当它是数据库访问或长时间计算的结果时,因为花费的时间越长,多个线程尝试的可能性就越高同时加载相同的值,如果没有一种机制确保只有一个线程将为所有调用线程加载数据,这将浪费资源。
所以这里假设您的 DataBuilder
的实例构建时间很长,或者您只需要确保所有线程对于给定的键都具有相同的实例,那么您确实需要一个 CacheLoader
它看起来像这样:
new CacheLoader<String, DataBuilder>() {
@Override
public DataBuilder load(String key) throws Exception {
return callSomeMethodToBuildItFromTheKey(key); // could be new DataBuilder(key)
}
}
感谢 CacheLoader
,您无需再显式调用 put
,因为您的缓存将由调用 cache.get(myKey)
或 [=22= 的线程在后台填充].
如果您想手动填充缓存,只需使用 put(K key, V value)
method like any Cache
如下:
public void addToCache(String key, DataBuilder dataBuilder) {
cache.put(key, dataBuilder);
}
如果您打算自己填充缓存,则不需要 CacheLoader
,您只需调用 build()
而不是 build(CacheLoader<? super K1,V1> loader)
来构建您的 Cache
实例(不再是 LoadingCache
)。
您的代码将是:
private final Cache<String, DataBuilder> cache =
CacheBuilder.newBuilder().maximumSize(10000000)
.removalListener(
RemovalListeners.asynchronous(new CustomListener(), executorService)
).build();
我有一个用例,我想从多个线程将条目填充到数据结构中,并在达到特定大小后开始删除旧记录。所以我决定为此使用 Guava Loading Cache。
我想从多个线程将条目填充到我的加载缓存中,我将基于逐出的策略设置为 Size Based Eviction
。
private final ScheduledExecutorService executorService = Executors
.newSingleThreadScheduledExecutor();
private final LoadingCache<String, DataBuilder> cache =
CacheBuilder.newBuilder().maximumSize(10000000)
.removalListener(RemovalListeners.asynchronous(new CustomListener(), executorService))
.build(new CacheLoader<String, DataBuilder>() {
@Override
public DataBuilder load(String key) throws Exception {
// what I should do here?
// return
}
});
// this will be called from multiple threads to populate the cache
public void addToCache(String key, DataBuilder dataBuilder) {
// what I should do here?
//cache.get(key).
}
我的 addToCache
方法将从多个线程调用以填充 cache
。我很困惑我应该在 addToCache
方法中做什么来填充缓存以及我的 load
方法是什么样的?
这里 DataBuilder
是我的构建器模式。
显然你的问题是你没有得到 CacheLoader
的主要目的。
A CacheLoader
用于在调用 get(K key)
or getUnchecked(K key)
时自动加载给定键(缓存中尚不存在)的值,即使我们有多个线程尝试要同时获取同一个键的值,实际上只有一个线程会加载该值,一旦完成,所有调用线程都将具有相同的值。
当加载值需要一些时间时,这通常很有用,例如当它是数据库访问或长时间计算的结果时,因为花费的时间越长,多个线程尝试的可能性就越高同时加载相同的值,如果没有一种机制确保只有一个线程将为所有调用线程加载数据,这将浪费资源。
所以这里假设您的 DataBuilder
的实例构建时间很长,或者您只需要确保所有线程对于给定的键都具有相同的实例,那么您确实需要一个 CacheLoader
它看起来像这样:
new CacheLoader<String, DataBuilder>() {
@Override
public DataBuilder load(String key) throws Exception {
return callSomeMethodToBuildItFromTheKey(key); // could be new DataBuilder(key)
}
}
感谢 CacheLoader
,您无需再显式调用 put
,因为您的缓存将由调用 cache.get(myKey)
或 [=22= 的线程在后台填充].
如果您想手动填充缓存,只需使用 put(K key, V value)
method like any Cache
如下:
public void addToCache(String key, DataBuilder dataBuilder) {
cache.put(key, dataBuilder);
}
如果您打算自己填充缓存,则不需要 CacheLoader
,您只需调用 build()
而不是 build(CacheLoader<? super K1,V1> loader)
来构建您的 Cache
实例(不再是 LoadingCache
)。
您的代码将是:
private final Cache<String, DataBuilder> cache =
CacheBuilder.newBuilder().maximumSize(10000000)
.removalListener(
RemovalListeners.asynchronous(new CustomListener(), executorService)
).build();