В Java
существует поточно-безопасная версия HashMap с именем ConcurrentHashMap и потокобезопасная версия TreeMap с именем ConcurrentSkipListMap, но нет ConcurrentHashSet
для HashSet.
Вместо этого обычно существует 4 способа использования поточно-безопасных Set
:
-
Set<String> mySet = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
-
Set<String> s = Collections.synchronizedSet(new HashSet<String>());
-
ConcurrentSkipListSet<E>
-
CopyOnWriteArraySet<E>
1 используйте keySet()
для ConcurrentHashMap
для достижения как Set
, так и потокобезопасных.
2 используйте synchronized
путь, кажется, что этот способ не рекомендуется.
3 основана на ConcurrentSkipListMap
и широко используется.
4 основан на CopyOnWriteArrayList, поэтому он имеет те же основные свойства CopyOnWriteArrayList
. Ниже показан выбор из CopyOnWriteArraySet
doc: http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArraySet.html
- Он лучше всего подходит для приложений, в которых обычно устанавливаются размеры набора малые операции только для чтения значительно превосходят число мутационных операций и вам необходимо предотвратить помехи между потоками во время обхода.
- Это поточно-безопасный.
- Мутативные операции (добавление, установка, удаление и т.д.) являются дорогостоящими, поскольку они обычно влекут за собой копирование всего базового массива.
- Итераторы не поддерживают операцию мутационного удаления.
- Обход между итераторами выполняется быстро и не может встретить помехи от других потоков.
- Итераторы полагаются на неизменные моментальные снимки массива во время создания итераторов.
Поскольку 1 и 3 обычно используются, почему существует CopyOnWriteArraySet
? Когда CopyOnWriteArraySet
полезно?
Добавлено: CopyOnWriteArraySet
основано на CopyOnWriteArrayList
, а операция contains
в структуре List
- O (n), а структура данных Set
- для высокой производительности contains
, может кто-нибудь объяснить это?