2

我正在尝试缓存一个int值(从数据库中计算一些东西)。这个计数可能需要很长时间,我想先尝试用 200 毫秒的超时时间来做。但如果失败了,我有两种情况:

  1. Mycache已填充,返回当前值并异步重新填充它。
  2. cache填充,通过填充来阻止并返回值。

我说的是“缓存”,但它实际上只是一个int值,我不确定cache这里是否需要一个完整的。我尝试过使用Guava 的供应商,但我找不到将我的特定用例与之集成的方法。

请记住,许多线程可以进入整个过程,我只希望第一个线程等待以防缓存未填充。其余的不应该等待并立即获取缓存值,如果其他线程完成重新填充缓存,则更新一个。

这是我现在拥有的示例代码:

public class CountRetriever {

private Supplier<Integer> cache = Suppliers.memoize(countSupplier());

private Supplier<Integer> countSupplier() {
    return new Supplier<Integer>() {
        @Override
        public Integer get() {
            // Do heavy count from the DB
        }
    };
}

public int getCount() {
    try {
        return submitAsyncFetch();
    } catch (Exception e) {
        // It takes too long, let's use the cache
        return cache.get();
    }
}

private Integer submitAsyncFetch() {
    return executor.submit(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            // Do heavy count from the DB
        }
    }).get(200, TimeUnit.MILLISECONDS);
}
}
4

1 回答 1

0

你有没有尝试过这样的事情?

private int Map<String,Integer> cache = new HashMap<String,Integer>();

public getValue(String key){
  synchronized(cache){
    Integer value = cache.get(key);
    if(value == null) { 
       value = getValue();
       cache.put(key,value);
    }
    return value;
  }
}

当然,如果在填充缓存时第二个线程进入,它将不得不等待。同样在此解决方案中,一次只有一个线程可以读取该值,因此您可能希望用ReadWriteLock替换同步块,尽管考虑到关键块的简单程度,我怀疑它会对性能产生重大影响。

于 2013-02-12T09:44:58.163 回答