2013-06-23 2 views
1

В java Мне нужно подсчитать элементы на ключ, поэтому я подумал об использовании ConcurrentMap с ключом, и, поскольку значение имеет AtomicInteger, однако мне интересно, есть ли лучший способ. Это не критический сервис, он просто используется для сбора статистики, поэтому я не против, если я опоздаю на 10 секунд с правильной статистикой или что-то вроде этого. Поэтому я задаюсь вопросом, есть ли более эффективная практика для него в стандартном java-параллелизме, или я снова остаюсь с тем, чтобы иметь дело с ConcurrentMap и с AtomicInteger (пример, который мог бы также решить проблему, был бы передачей сообщений, может быть, если да, то как может это мне помочь?) (лучше всего было бы с примером ...), что бы не было проблем с производительностью, и было бы безопасно, и было бы легко использовать, я не возражаю против латентности.Какова наилучшая практика для подсчета на каждый ключ в java

ответ

4

Guava предоставляет ConcurrentHashMultiset. Это параллельная реализация Multiset, которая фактически представляет собой набор, позволяющий дублировать. Вы можете add(E) и remove(Object), как обычно, но также получить count(Object) элемента в Multiset.

Фактически, this is implemented с использованием подложки ConcurrentHashMap<E, AtomicInteger>, поэтому ваша практика прекрасна. Однако:

  • Интерфейс Multiset обеспечивает более хорошую абстракцию, он распространяется даже Collection.
  • Правильное управление этими AtomicIntegers самостоятельно - это сложное дело. Быстро взглянув на код Гуавы, вы должны дать представление о проблемах, которые возникают при одновременном программировании: вам нужно много compareAndSet s и бесконечных циклов while, чтобы убедиться, что получены правильные результаты.
+0

звучит идеально. Я смотрел на реализацию, как вы предполагали, и действительно ее нетривиально. поэтому, если я добавлю 10 элементов типа Apple, он не будет хранить 10 элементов, поскольку его набор будет считать, что яблоко будет 10, верно? – Jas

+0

@Jason Yup, у него будет только одна запись на карте для '' Apple'', содержащая 'AtomicInteger' со значением' 10'. Хорошо, что вам больше не нужно об этом думать: все это абстрагируется, и вы можете просто использовать интерфейс Multiset для работы с ним. –

+0

спасибо, так же, как и боковое наблюдение, я вижу, что есть дискуссии о его производительности. https://groups.google.com/forum/#!topic/guava-discuss/KJuv1P77vRI – Jas

0

Да, я думаю, что это правильное направление, поэтому я действительно не понимаю, почему, по вашему мнению, это непросто. Просто используйте специфические функции с параллельной картой. То есть для обновления статистики будет:

AtomicInteger newCounter = new AtomicInteger(1); 
AtomicInteger existingCounter = map.putIfAbsent(key, newCounter); 
if(existingCounter != null) 
    existingCounter.incrementAndGet();