0

I have a question. If I use expireAfterAccess and suppose my entry gets expired after 2 hours. Now if I call get() for that entry after some time (say 5 hours), will it get cached again? or will it expire for good?

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;
            };
        });
4

1 回答 1

0

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

When in doubt and the documentation isn't clear enough you can always test it:

@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);
}

It certainly isn't something that you would put in your tests but this type of exercise can be very useful for better understanding how a library works.

You can also learn how a class works from reading/stepping-through its unit/functional tests. e.g. guava/CacheExpirationTest.java at master · google/guava.

于 2017-01-31T15:08:52.750 回答