2013-06-08 9 views
3

У меня есть сценарий, в котором неизвестное количество потоков добавляет элементы в коллекцию на сервере. Данные в этой коллекции не нужно сортировать, и она также не будет повторяться. Только две простые операции должны работать над этой коллекции:Какую параллельную коллекцию использовать?

  1. Добавление элемента (и удаления старого элемента в некоторых случаях)
  2. Чтение всех элементов из коллекции (не один на один, но и всей коллекции, чтобы Конечно, элементы можно также перенести в другую коллекцию, которая затем сериализуется впоследствии.)

Какая коллекция будет идеально подходит для этого прецедента? Я бы выбрал ConcurrentHashMap, бу, я не знаю, хороший ли этот выбор.

Редактировать: Я забыл одно важное требование: если элемент определенного вида уже присутствует в этой коллекции и добавлен другой такой же вид, тогда старый должен быть удален до добавления нового. Для этого требования я хотел использовать хэш-значения, чтобы избежать поиска. Объекты, которые хранятся, просты: они содержат уникальное имя пользователя и некоторые строки и ints. Имя пользователя объекта должно использоваться как ключ.

+1

Почему ConcurrentHashMap? Вы ищете пары ключ-значение? –

+1

Если это все, что вам действительно нужно сделать, то «CopyOnWriteArrayList» выполнит эту работу; однако будьте осторожны, чтобы одна итерация создавала _new copy_ каждый раз. Таким образом, если вы ожидаете большого количества читателей, это может быть не идеальный выбор ... – fge

+1

Согласно документу очень дорого добавлять и удалять элементы из CopyOnWriteArrayList. – user1812379

ответ

3

Да, ConcurrentHashMap подходит для этого. Используйте имя пользователя как тип ключа (K) и соответствующую информацию пользователя («некоторые строки и ints») как тип значения (V) на карте. Используйте put, чтобы добавить новые пары ключ-значение, remove, чтобы удалить пары ключ-значение, и entrySet, чтобы получить все пары ключ-значение в контейнере (если это то, что вы подразумеваете под «чтением всех элементов из коллекции»).

+0

Да, я сделал это: значение - это сам объект, а ключ - свойство объекта. Я вызвал вызовы методов типа 'put()' и 'remove (') с 'synchronized (map) {.....}'. Существуют ли какие-либо правила, как «ConcurrentHashMap» должна быть правильно настроена? Параллельная ситуация по умолчанию 16 может часто быть излишней. – user1812379

+2

@ user1812379: Вам не нужно использовать 'synchronized (map) {...}', чтобы использовать 'put',' remove' или любую другую операцию на экземплярах CHM, что может привести к поражению цели использования класса CHM. Операции с CHM уже являются атомарными, см. Документацию для получения более подробной информации. Что касается наиболее подходящего значения для 'concurrencyLevel', у Javadoc есть некоторые заметки, но если это действительно важно, вы должны измерять (при реальных нагрузках) себя, так как« лучшее »значение отличается от ситуаций (поэтому вам разрешено его настраивать). – cic

+0

См. Также http://stackoverflow.com/questions/510632/whats-the-difference-between-concurrenthashmap-and-collections-synchronizedmap. – cic

1

Я считаю, что существует реализация параллельного списка в java.util.concurrent. CopyOnWriteArrayList, которая может быть полезна для вашего требования.

или вы можете использовать:

List<Object> objList = Collections.synchronizedList(new ArrayList<Object>()); 
+0

Спасибо, но это не очень подходит для многих мутационных операций, таких как добавление элементов. – user1812379

1

Это не является частью стандартной библиотеки, но вы можете использовать this concurrent doubly linked list. Его итератор слабо согласован и не будет бросать ConcurrentModificationException, или вы можете использовать toArray и прокрутить возвращаемый массив.

1

Я думаю, что лучше всего использовать на самом деле ConcurrentSkipListSet. причина:

итераторы слабо совместимые, возвращающие элементы, отражающие состояние набора в какой-то момент на или с момента создания итератора. Они не выбрасывают ConcurrentModificationException и могут действовать одновременно с другими операциями. Восходящие упорядоченные виды и их итераторы быстрее, чем нисходящие.

это означает, что вы можете просмотреть весь список и прочитать все элементы при добавлении других элементов. он полностью параллелен!

Обратите внимание, что при добавлении элементов требуется время O (logN).

+0

Спасибо. Да, когда данные в ConcurrentHashMap читаются, он уже может быть устаревшим, но чтение хэш-значений выполняется быстрее, чем обход дерева. – user1812379

+1

, но одно из требований заключается в том, что вы могли одновременно читать все элементы. итератор ConcurrentHashMap не предназначен для работы с несколькими потоками: «итераторы предназначены для использования только по одному потоку за раз». http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html –

+0

Извините, потому что в этом отношении я был неточным: я не хочу читать каждый элемент, но сразу прочитайте все данные, а затем отправьте их на удаленный хост. Затем клиент считывает объект из потока и сохраняет данные в TreeSet, чтобы отобразить его в определенном порядке. – user1812379

Смежные вопросы