この問題に取り組む主流の方法は、タイマースレッドを使用して、指定された間隔でキャッシュを更新することです。ただし、新しいスレッドを作成する必要がないため、考えられる実装は、疑似タイミングのキャッシュ更新の実装です。基本的に、キャッシュアクセサー(putおよびgetメソッド)にチェックを挿入し、クライアントがこのメソッドを使用するたびに、putまたはgetアクションを実行する前にキャッシュを更新する必要があるかどうかをチェックします。これは大まかな考えです:
class YourCache {
// holds the last time the cache has been refreshed in millis
private volatile long lastRefreshDate;
// indicates that cache is currently refreshing entries
private volatile boolean cacheCurrentlyRefreshing;
private Map cache = // Your concurrent map cache...
public void put(Object key, Object element) {
if (cacheNeedsRefresh()) {
refresh();
}
map.put(key, element);
}
public Object get(Object key) {
if (cacheNeedsRefresh()) {
refresh();
}
return map.get(key);
}
private boolean cacheNeedsRefresh() {
// make sure that cache is not currently being refreshed by some
// other thread.
if (cacheCurrentlyRefreshing) {
return false;
}
return (now - lastRefreshDate) >= REFRESH_INTERVAL;
}
private void refresh() {
// make sure the cache did not start refreshing between cacheNeedsRefresh()
// and refresh() by some other thread.
if (cacheCurrentlyRefreshing) {
return;
}
// signal to other threads that cache is currently being refreshed.
cacheCurrentlyRefreshing = true;
try {
// refresh your cache contents here
} finally {
// set the lastRefreshDate and signal that cache has finished
// refreshing to other threads.
lastRefreshDate = System.currentTimeMillis();
cahceCurrentlyRefreshing = false;
}
}
}
個人的にはそうすることは考えていませんが、タイマースレッドを作成したくない、または作成できない場合は、これが選択肢になる可能性があります。
この実装はロックを回避しますが、レースイベントのために更新が重複する傾向があることに注意してください。これで要件に問題がなければ、問題はありません。ただし、より厳しい要件がある場合は、スレッドを適切に同期してレースイベントを回避するために、ロックを設定する必要があります。