Я реализую уровень кэширования с высокой пропускной способностью на Java. К кешу одновременно обращаются сотни потоков, и в нем хранятся большие объекты.
Я использую ConcurrentHashMap с объектами SoftReference, чтобы позволить JVM освобождать память под нагрузкой. Вот упрощенная версия моего кода:
public class SoftCache {
private final ConcurrentHashMap map = new ConcurrentHashMap();
public void put(K key, V value) {
map.put(key, new SoftReference(value));
}
public V get(K key) {
SoftReference ref = map.get(key);
return ref != null ? ref.get() : null;
}
public void cleanup() {
for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = it.next();
if (entry.getValue().get() == null) {
it.remove();
}
}
}
}
Проблемы, которые я наблюдаю:
Иногда объекты неожиданно исчезают из кэша, даже если использование памяти низкое.
Иногда очистка() приводит к высокой загрузке ЦП при большой нагрузке.
Я не уверен, что это так. потокобезопасен, когда cleanup() выполняется одновременно с get() и put().
Мои вопросы:
Есть ли проблемы с параллельным доступом в этой реализации, особенно с сотнями потоков?
Как это сделать? SoftReferences взаимодействуют со сборщиком мусора при разной нехватке памяти? Почему кэшированные объекты могут неожиданно исчезнуть?
Я реализую уровень кэширования с высокой пропускной способностью на Java. К кешу одновременно обращаются сотни потоков, и в нем хранятся большие объекты. Я использую ConcurrentHashMap с объектами SoftReference, чтобы позволить JVM освобождать память под нагрузкой. Вот упрощенная версия моего кода: [code]public class SoftCache { private final ConcurrentHashMap map = new ConcurrentHashMap();
public void put(K key, V value) { map.put(key, new SoftReference(value)); }
public V get(K key) { SoftReference ref = map.get(key); return ref != null ? ref.get() : null; }
public void cleanup() { for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = it.next(); if (entry.getValue().get() == null) { it.remove(); } } } } [/code] [b]Проблемы, которые я наблюдаю:[/b] [list] [*]Иногда объекты неожиданно исчезают из кэша, даже если использование памяти низкое.
[*]Иногда очистка() приводит к высокой загрузке ЦП при большой нагрузке.
[*]Я не уверен, что это так. потокобезопасен, когда cleanup() выполняется одновременно с get() и put().
[/list] [b]Мои вопросы:[/b] [list] [*]Есть ли [b]проблемы с параллельным доступом[/b] в этой реализации, особенно с сотнями потоков?
[*]Как это сделать? [b]SoftReferences взаимодействуют со сборщиком мусора[/b] при разной нехватке памяти? Почему кэшированные объекты могут неожиданно исчезнуть?