为什么设置expireAfterAccess不起作用?

时间:2013-03-07 20:21:48

标签: java caching testing guava

为什么timedCachetest在最后一行失败?为什么60秒后缓存不为空?

package com.test.cache;

import java.util.concurrent.TimeUnit;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

public class CacheTest {
    private static final int MAXIMUM_SIZE = 10;
    private static final int CONCURRENCY_LEVEL = 1;
    private static final long EXPIRE_AFTER_ACCESS = 60;
    Cache<String, Thing> cache;
    private static TimeUnit unit = TimeUnit.SECONDS;
    private static long sec = 1000;

    @Before
    public void setUp() throws Exception {
        cache = CacheBuilder.newBuilder().maximumSize(MAXIMUM_SIZE).concurrencyLevel(CONCURRENCY_LEVEL).expireAfterAccess(EXPIRE_AFTER_ACCESS, unit).build();
    }

    @After
    public void tearDown() {
        cache = null;
    }

    @Test
    public void simpleCachetest() {
        String key = "key";
        Integer hc = key.hashCode();
        Thing thing = new Thing(key);
        cache.put(key, thing);
        thing = cache.getIfPresent(key);
        Assert.assertNotNull(thing);
        Assert.assertEquals(hc, thing.getValue());
        Assert.assertEquals(key, thing.getName());
        Assert.assertEquals(1, cache.size());
    }

    @Test
    public void timedCachetest() {
        String key = "key";
        Thing thing = new Thing(key);
        Assert.assertEquals(0, cache.size());
        cache.put(key, thing);
        Assert.assertEquals(1, cache.size());
        try {
            thing = cache.getIfPresent(key);
            long millis = 100 * sec;
            Thread.sleep(millis);
            // cache.invalidateAll();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Assert.assertNotNull(thing);
        Assert.assertEquals(key, thing.getName());
        Assert.assertEquals(0, cache.size());
    }

    class Thing {
        public Thing(String key) {
            this.name = key;
            this.value = key.hashCode();
        }

        public String getName() {
            return name;
        }

        public Integer getValue() {
            return value;
        }

        private String name;
        private Integer value;
    }
}

1 个答案:

答案 0 :(得分:9)

CacheBuilder Javadoc:

中已经说明了
  

如果请求expireAfterWrite或expireAfterAccess,则可能会在每次缓存修改,偶尔的缓存访问或对Cache.cleanUp()的调用时逐出条目。过期的条目可以在Cache.size()中计算,但对于读取或写入操作永远不可见。

CacheBuilder缓存可以在特别请求时进行维护,也可以在缓存突变的一部分进行维护,或偶尔进行读取。它没有例如启动一个线程来做缓存维护,因为a)线程相对较重,b)某些环境限制线程的创建。