В java Мне нужно подсчитать элементы на ключ, поэтому я подумал об использовании ConcurrentMap
с ключом, и, поскольку значение имеет AtomicInteger
, однако мне интересно, есть ли лучший способ. Это не критический сервис, он просто используется для сбора статистики, поэтому я не против, если я опоздаю на 10 секунд с правильной статистикой или что-то вроде этого. Поэтому я задаюсь вопросом, есть ли более эффективная практика для него в стандартном java-параллелизме, или я снова остаюсь с тем, чтобы иметь дело с ConcurrentMap и с AtomicInteger
(пример, который мог бы также решить проблему, был бы передачей сообщений, может быть, если да, то как может это мне помочь?) (лучше всего было бы с примером ...), что бы не было проблем с производительностью, и было бы безопасно, и было бы легко использовать, я не возражаю против латентности.Какова наилучшая практика для подсчета на каждый ключ в java
1
A
ответ
4
Guava предоставляет ConcurrentHashMultiset
. Это параллельная реализация Multiset
, которая фактически представляет собой набор, позволяющий дублировать. Вы можете add(E)
и remove(Object)
, как обычно, но также получить count(Object)
элемента в Multiset
.
Фактически, this is implemented с использованием подложки ConcurrentHashMap<E, AtomicInteger>
, поэтому ваша практика прекрасна. Однако:
- Интерфейс
Multiset
обеспечивает более хорошую абстракцию, он распространяется дажеCollection
. - Правильное управление этими
AtomicIntegers
самостоятельно - это сложное дело. Быстро взглянув на код Гуавы, вы должны дать представление о проблемах, которые возникают при одновременном программировании: вам нужно многоcompareAndSet
s и бесконечных цикловwhile
, чтобы убедиться, что получены правильные результаты.
0
Да, я думаю, что это правильное направление, поэтому я действительно не понимаю, почему, по вашему мнению, это непросто. Просто используйте специфические функции с параллельной картой. То есть для обновления статистики будет:
AtomicInteger newCounter = new AtomicInteger(1);
AtomicInteger existingCounter = map.putIfAbsent(key, newCounter);
if(existingCounter != null)
existingCounter.incrementAndGet();
звучит идеально. Я смотрел на реализацию, как вы предполагали, и действительно ее нетривиально. поэтому, если я добавлю 10 элементов типа Apple, он не будет хранить 10 элементов, поскольку его набор будет считать, что яблоко будет 10, верно? – Jas
@Jason Yup, у него будет только одна запись на карте для '' Apple'', содержащая 'AtomicInteger' со значением' 10'. Хорошо, что вам больше не нужно об этом думать: все это абстрагируется, и вы можете просто использовать интерфейс Multiset для работы с ним. –
спасибо, так же, как и боковое наблюдение, я вижу, что есть дискуссии о его производительности. https://groups.google.com/forum/#!topic/guava-discuss/KJuv1P77vRI – Jas