番石榴缓存expireAfterAccess问题

Guava cache expireAfterAccess issue

我有一个问题。如果我使用 expireAfterAccess 并假设我的条目在 2 小时后过期。现在,如果我在一段时间后(比如 5 小时)为该条目调用 get(),它会再次被缓存吗?还是会永远过期?

private final LoadingCache<String, Map<String, PinPointRule>> pinPointRuleCache = CacheBuilder.newBuilder().maximumSize(500000)
        .expireAfterAccess(2, TimeUnit.HOURS).build(new CacheLoader<String, Map<String, PinPointRule>>(){
            @Override
            public Map<String, PinPointRule> load(String dummyToken) throws Exception {
                return loadPinPointRules(dummyToken);
            }

            public ListenableFuture<Map<String,PinPointRule>> reload(final String key, final Map<String,PinPointRule> oldValue) throws Exception {
                ListenableFutureTask<Map<String,PinPointRule>> task = ListenableFutureTask.create(new Callable<Map<String,PinPointRule>>() {
                    public Map<String,PinPointRule> call() throws Exception {
                        long start = System.nanoTime();
                        LOGGER.info("LoadingCache Reload");
                        try {
                            return loadPinPointRules(key);
                        } catch (Exception e) {
                            LOGGER.error("Error while loading pinpoint rules. Returning old value. Exception :: {}", getStackTrace(e));
                        } finally {
                            LOGGER.info("Time taken in reloading pinpoint rule: {} ", TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start));
                        }
                        return oldValue;
                    }
                });
                executor.execute(task);
                return task;
            };
        });

Xaerxess 、"it will get cached again (i.e. load method on CacheLoader you provided will be called), it's how caches work."

如有疑问且文档不够清晰,您可以随时对其进行测试:

@Test
public void expireAfterAccessReloadsCache() throws Exception {
    CacheLoader<Integer, String> cacheLoader = Mockito.mock(CacheLoader.class);
    Integer testKey = 1;
    String testValue = "1";
    when(cacheLoader.load(testKey)).thenReturn(testValue);
    FakeTicker fakeTicker = new FakeTicker();
    LoadingCache<Integer, String> loadingCache = CacheBuilder.newBuilder()
            .ticker(fakeTicker)
            .expireAfterAccess(2, TimeUnit.HOURS)
            .build(cacheLoader);
    assert testValue.equals(loadingCache.get(testKey));
    verify(cacheLoader).load(testKey);
    assert testValue.equals(loadingCache.get(testKey));
    verifyZeroInteractions(cacheLoader);
    fakeTicker.advance(1, TimeUnit.HOURS);
    assert testValue.equals(loadingCache.get(testKey));
    verifyZeroInteractions(cacheLoader);
    fakeTicker.advance(4, TimeUnit.HOURS);
    assert testValue.equals(loadingCache.get(testKey));
    verify(cacheLoader, times(2)).load(testKey);
    assert testValue.equals(loadingCache.get(testKey));
    verifyZeroInteractions(cacheLoader);
}

这当然不是您要放在测试中的东西,但这种类型的练习对于更好地理解库的工作原理非常有用。

您还可以通过 reading/stepping-through 它的 unit/functional 测试了解 class 的工作原理。例如guava/CacheExpirationTest.java at master · google/guava.