Параллельная карта с фиксированным размером
Мне нужна карта со следующими требованиями:
Это должно быть в высокой степени одновременно.
put()
,get()
а такжеremove()
методы могут вызываться несколькими потоками одновременно.Он должен быть фиксированного размера. Если размер
HashMap
достигает максимального значения (например, 10000), добавление новой записи на карту не допускается. Это не может быть LRU-кеш, где самая старая запись удаляется при достижении максимального размера.
ConcurrentHashMap
может удовлетворить #1. Но не уверен, как #2 может быть реализован поверх ConcurrentHashMap
без влияния на параллелизм (добавление пользовательского put()
метод, который добавит на карту только тогда, когда размер меньше, чем максимальный размер, должен быть "синхронизирован". Это победит цель использования одновременных HashMap
).
Пожалуйста, поделись своими мыслями.
6 ответов
Вы могли бы реализовать карту, которая делегирует ConcurrentHashMap, используя счетный семафор, чтобы ограничить количество элементов на карте. Класс Semaphore использует атомарно обновленный int для отслеживания разрешений, поэтому он не потребует дополнительных затрат.
Вы можете сделать все это самостоятельно, и только арсенал java SE может предоставить то, что вам нужно, но я настоятельно рекомендую более простую и более масштабируемую методологию, так как выполнение всей этой работы самостоятельно будет заново изобретать колесо. Попробуйте один из них в сетках данных памяти:
Например, в ehcache вы можете достичь того, что вы хотите, с помощью конфигурации, аналогичной:
<cache
name="myCache"
maxElementsInMemory="10000"
eternal="true"
overflowToDisk="false" />
Попробуй это:
public static class ConcurrentFixedMap<K, V> extends LinkedHashMap<K, V> {
private final int MAX_ENTRIES;
private ConcurrentFixedMap(int size) {
super(size);
this.MAX_ENTRIES = size;
}
public static <K, V> Map<K, V> init(int size) {
return Collections.synchronizedMap(new ConcurrentFixedMap<>(size));
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > MAX_ENTRIES;
}
}
Как насчет поддержания размера Hashmap для обеспечения общего количества вставленных элементов? Вы можете использовать AtomicInteger, чтобы вам не приходилось синхронизировать / блокировать обычное int и пожертвовать преимуществами использования ConcurrentHashMap.
Если вы используете ConcurrentHashMap, который здесь очевиден, используйте concurrencyLevel
вход в конструктор для увеличения пропускной способности - это сегментирует карту на несколько зон, чтобы избежать конфликтов пут.
Чтобы удовлетворить мою потребность в ограниченной параллельной хэш-карте: проверьте размер карты перед ее использованием.