Google Guava Cache 是否在同一线程上加载?

Does Google Guava Cache load on same thread?

Google Guava Cache 是否默认在同一个线程上加载缓存?

代码:

cache = CacheBuilder
    .newBuilder()
    .refreshAfterWrite(2, TimeUnit.SECONDS)
    .build(new CacheLoader<String,String>() {
        @Override
        public String load(String s) throws Exception {
            return addCache(s);
        }
});

是否会在不同的线程上调用 addCache?据我所知,这是一个同步调用,但我不确定。

这里有一个简单的测试可以知道:

    System.out.println("Thread.currentThread() = " + Thread.currentThread());
    LoadingCache<String, String> cache = CacheBuilder
        .newBuilder()
        .refreshAfterWrite(2, TimeUnit.SECONDS)
        .build(new CacheLoader<String, String>() {
            @Override
            public String load(String s) throws Exception {
                System.out.println("Thread.currentThread() = " + Thread.currentThread());
                return "world";
            }
        });
    cache.get("hello");

输出:

Thread.currentThread() = Thread[main,5,main]
Thread.currentThread() = Thread[main,5,main]

当然,如文档所示,如果另一个线程已经开始加载该键的值,则当前线程不会重新加载它:它将等待另一个线程加载该值:

If another call to get(K) or getUnchecked(K) is currently loading the value for key, simply waits for that thread to finish and returns its loaded value.

添加到 JB Nizet 的回答中,您可以了解为什么 Guava 默认避免使缓存成为多线程 here:

The reason for this is as follows: if we wanted to perform Cache maintenance continuously, we would need to create a thread, and its operations would be competing with user operations for shared locks. Additionally, some environments restrict the creation of threads, which would make CacheBuilder unusable in that environment.