2015-06-08 3 views
6

В Java есть множество разных коллекций, предназначенных для параллелизма и безопасности потоков, и я не понимаю, что выбрать для моей ситуации.Самый эффективный, но потокобезопасный список/набор

Несколько потоков могут звонить .add() и .remove(), и я буду копировать этот список часто с чем-то вроде List<T> newList = new ArrayList<T>(concurrentList). Я никогда не буду перебирать параллельный список.

Я думал о чем-то вроде CopyOnWriteArrayList, но я читал, что он может быть очень неэффективным, потому что он копирует себя каждый раз, когда он изменен. Я надеюсь найти хороший компромисс между безопасностью и эффективностью.

Каков наилучший список (или набор) для этой ситуации?

+1

Вы уверены, что вам нужен список? Будет ли карта или набор соответствовать вашим потребностям. Гораздо проще иметь одновременный доступ к карте или набору, чем список. – bhspencer

+0

@bhspencer Да, я думаю, что набор может работать. – RogueCSDev

+0

Если вы обычно добавляете и удаляете элементы с конца, и вы часто копируете список, наиболее эффективная структура данных будет неизменным односвязным списком, к которому, к сожалению, нет java-файла, но это очень простая структура данных, поэтому вы можете быстро реализуйте его самостоятельно. – SpiderPig

ответ

1

Вы можете захотеть взглянуть на, будет ли ctrie быть подходящим для вашего случая использования - он имеет поточно-add и remove операции, и «копирование» (в действительности, принимая снимок) структуры данных работают в O (1). Я знаю о двух реализациях JVM структуры данных: implementation one, implementation two.

3

Как @SpiderPig сказал, лучший сценарий с List был бы неизменным, односвязным списком.

Однако, глядя на то, что делается здесь, необязательно List (комментарий @ bhspencer). A ConcurrentSkipListSet будет работать наиболее эффективно (@augray).

This Related Thread принятый ответ предлагает более глубокое понимание плюсов и минусов различных параллельных коллекций.

+1

Обратите внимание, что synchronizedSet также имеет объектную блокировку (все вызовы к ней блокируются, и только один поток может работать с ней за раз). Если вы можете найти способ использования параллельного объекта, а не синхронизированного, вы, вероятно, будете лучше с точки зрения производительности (т. Е. Предполагая, что этот ресурс влияет на перенос, который кажется безопасным предположением, учитывая этот вопрос). – augray

+1

Если вы хотите использовать набор, [ConcurrentSkipListSet] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentSkipListSet.html), вероятно, будет более эффективным, чем synchronizedSet. С * Java Concurrency in Practice *: «Замена синхронизированных коллекций с одновременными коллекциями может обеспечить значительные улучшения масштабируемости с небольшим риском». – augray

0
Collections.newSetFromMap(new ConcurrentHashMap<...>()) 

Как правило, это нормальный набор (HashSet - действительно модифицированная оболочка поверх HashMap). Он предлагает как преимущества производительности/concurrecy от ConcurrentHashMap, так и не имеет дополнительных функций, таких как ConcurrentSkipListSet (заказы), списки COW (копирование каждой модификации) или параллельные очереди (упорядочение FIFO/LIFO).

Редактировать: я не видел комментарий @ bhspencer на исходное сообщение, извинения за кражу прожектора.

0

Хэш-хэш, основанный на хэшировании, будет лучше, чем List. Добавить последний и удалить сначала будет хорошо с LinkedList. Поиск будет быстрым в arraylist, основываясь на индексе массива.

Thanks,

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