Я создаю кеш мемоизации со следующими характеристиками:
- a cache miss will result in computing and storing an entry
- this computation is very expensive
- это вычисление идемпотентно
- unbounded (entries never removed) since:
- the inputs would result in at most 500 entries
- каждая сохраненная запись очень мала
- кеш относительно недолговечен (обычно менее часа)
- в целом использование памяти не является проблемой
- будут тысячи чтений - за время жизни кеша я ожидаю 99,9% + попаданий в кеш
- должен быть потокобезопасным
Что будет иметь лучшие характеристики или при каких условиях одно решение будет предпочтительнее другого?
ThreadLocal HashMap:
class MyCache {
private static class LocalMyCache {
final Map<K,V> map = new HashMap<K,V>();
V get(K key) {
V val = map.get(key);
if (val == null) {
val = computeVal(key);
map.put(key, val);
}
return val;
}
}
private final ThreadLocal<LocalMyCache> localCaches = new ThreadLocal<LocalMyCache>() {
protected LocalMyCache initialValue() {
return new LocalMyCache();
}
};
public V get(K key) {
return localCaches.get().get(key);
}
}
ConcurrentHashMap:
class MyCache {
private final ConcurrentHashMap<K,V> map = new ConcurrentHashMap<K,V>();
public V get(K key) {
V val = map.get(key);
if (val == null) {
val = computeVal(key);
map.put(key, val);
}
return val;
}
}
Я полагаю, что решение ThreadLocal изначально было бы медленнее, если бы было много потоков из-за всех пропусков кеша на поток, но за тысячи чтений амортизированная стоимость будет ниже, чем решение ConcurrentHashMap. Моя интуиция верна?
Или есть еще лучшее решение?