In my application, I'd like to have a cache that will be updated daily by an expensive operation (for example, fetching from remote and computing locally). The idea is every day, it will fetch and compute the latest cache for today. And at any time of today, any thread should be able to read from/write to the daily cache. And it's fine to serve the old data when the expensive operation is running daily and should not block any requests at any time.
I have written a simple code to illustrate the idea but not sure if it's the best practice or even correct in terms of multithreading. For example,
- is
volatilerequired? - What will happen if there is a cache reassignment finished in the middle of a get or put.
Any suggestion will be much appreciated!
public class DailyCache {
private volatile ConcurrentHashMap<String, String> cache;
public DailyCache() {
cache = expensiveCalculation();
Executors.newScheduledThreadPool(1)
.scheduleAtFixedRate(() -> cache = expensiveCalculation(), 1, 1, TimeUnit.DAYS);
}
public String get(String key) {
return cache.get(key);
}
public void put(String key, String value) {
cache.put(key, value);
}
public ConcurrentHashMap<String, String> expensiveCalculation() {
// an expensive operation to fetch the cache for today
}
}
CodePudding user response:
Executor service
First of all, you need to capture the reference returned from the call Executors.newScheduledThreadPool(1). You must store that reference somewhere in your app for eventual shutdown. If you neglect to shut down an executor service, it’s backing pool of threads may continue to run after your app exits, like a zombie
