【发布时间】:2015-08-18 04:32:30
【问题描述】:
我有一个我认为是 Guava 缓存的简单用途。但是,这种行为对我来说并不直观。我有一个 POJO,Foo,属性为 Id (Integer)。在检索Foo 的实例时,我使用Integer 作为缓存的键。如果我将三个项目放入缓存中,并休眠足够长的时间以使所有内容都过期,那么无论键值如何,我都会期望相同的行为。问题是我根据使用的密钥看到不同的行为。我将三个对象放入缓存中:1000、2000 和 3000。
[main] INFO CacheTestCase - 3000 creating foo, 1000
[main] INFO CacheTestCase - 3000 creating foo, 2000
[main] INFO CacheTestCase - 3000 creating foo, 3000
[main] INFO CacheTestCase - 3000 Sleeping to let some cache expire . . .
[main] INFO CacheTestCase - 3000 Continuing . . .
[main] INFO CacheTestCase - 3000 Removed, 1000
[main] INFO CacheTestCase - 3000 Removed, 2000
[main] INFO CacheTestCase - 3000 creating foo, 1000
[main] INFO CacheTestCase -
请注意,在上述运行中,键为 3000 的 Foo 实例并未从缓存中删除。下面是相同代码的输出,但我使用了 4000 而不是 3000 的键。
[main] INFO CacheTestCase - 4000 creating foo, 1000
[main] INFO CacheTestCase - 4000 creating foo, 2000
[main] INFO CacheTestCase - 4000 creating foo, 4000
[main] INFO CacheTestCase - 4000 Sleeping to let some cache expire . . .
[main] INFO CacheTestCase - 4000 Continuing . . .
[main] INFO CacheTestCase - 4000 Removed, 1000
[main] INFO CacheTestCase - 4000 Removed, 2000
[main] INFO CacheTestCase - 4000 Removed, 4000
[main] INFO CacheTestCase - 4000 creating foo, 1000
当然,我做了一些非常愚蠢的事情。这是我的 MCVE:
package org.dlm.guava;
import com.google.common.cache.*;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* Created by dmcreynolds on 8/17/2015.
*/
public class CacheTestCase {
static final Logger log = LoggerFactory.getLogger("CacheTestCase");
String p = ""; // just to make the log messages different
int DELAY = 10000; // ms
@Test
public void testCache123() throws Exception {
p = "3000";
LoadingCache<Integer, Foo> fooCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(100, TimeUnit.MILLISECONDS)
.removalListener(new FooRemovalListener())
.build(
new CacheLoader<Integer, Foo>() {
public Foo load(Integer key) throws Exception {
return createExpensiveFoo(key);
}
});
fooCache.get(1000);
fooCache.get(2000);
fooCache.get(3000);
log.info(p + " Sleeping to let some cache expire . . .");
Thread.sleep(DELAY);
log.info(p + " Continuing . . .");
fooCache.get(1000);
}
private Foo createExpensiveFoo(Integer key) {
log.info(p+" creating foo, " + key);
return new Foo(key);
}
public class FooRemovalListener
implements RemovalListener<Integer, Foo> {
public void onRemoval(RemovalNotification<Integer, Foo> removal) {
removal.getCause();
log.info(p+" Removed, " + removal.getKey().hashCode());
}
}
/**
* POJO Foo
*/
public class Foo {
private Integer id;
public Foo(Integer newVal) {
this.id = newVal;
}
public Integer getId() {
return id;
}
public void setId(Integer newVal) {
this.id = newVal;
}
}
}
【问题讨论】: