Какие коллекции Java синхронизированы, а какие нет?
Пример: HashSet не синхронизирован
Какие коллекции Java синхронизированы, а какие нет?
Пример: HashSet не синхронизирован
Существует три группы коллекций.
Collections.synchronizedXxx()
Короче говоря, ни одна из коллекций, которые я бы рекомендовал вам использовать, синхронизирована.
Вы можете получить синхронизированную версию Java Collection
с
Collections.synchronizedCollection(Collection<T> c)
[javadoc]
Простой ответ: ни одна реализация Collection
не синхронизируется, потому что synchronized
не является свойством класса, он применим только к методам и блокам.
Полагаю, вы хотите знать, какие реализации являются поточно-ориентированными, какие классы из инфраструктуры java collection можно безопасно использовать в многопоточной среде.
Информация всегда включена в javadoc (как здесь: Arraylist - который не является потокобезопасным)
Потокобезопасные Коллекции -
Потокобезопасен без синхронизации всей карты. Очень быстрое чтение, когда запись выполняется с блокировкой. Нет блокировки на уровне объекта. Использует множество блокировок.
Синхронизация на уровне объекта. И чтение, и запись получают блокировку. Блокировка коллекции имеет недостаток производительности. Может вызвать конфликт
Вектор
Хеш-таблица
CopyOnWriteArrayList
CopyOnWriteArraySet
стек
Остальные все не нить безопасны
ArrayList, LinkedList, HashSet, LinkedHashset и TreeSet в интерфейсе коллекции и HashMap, LinkedHashMap и Treemap являются несинхронизированными.
Вектор в интерфейсе коллекции Синхронизированный
Предыдущий пример совершенно неправильный.
Прежде всего, вы не получаете доступ из разных потоков списка, который вы только что синхронизировали, вы не можете доказать, что синхронизация выполняется правильно, вы не можете доказать, что процесс добавления является атомарным. Во-вторых, синхронизированное предложение по самому списку является плохой практикой, вы не знаете, будет ли оптимизатор использовать элемент в списке для синхронизации, что приведет к неожиданному поведению. Кроме того, синхронизация - это доступ к элементам в списке чтения/записи, а не к самому списку. Выньте Collections.synchronized и просмотрите вывод. Попробуйте много раз. Пример:
class ProcessSomething {
private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
private void calculate() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
private void calculate2() {
for (int i = 0; i < 10000; i++) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
}
integerList.add(new Random().nextInt(100));
}
}
public void process() {
Long start = System.currentTimeMillis();
Thread t1 = new Thread(new Runnable() {
public void run() {
calculate();
}
});
t1.start();
Thread t2 = new Thread(new Runnable() {
public void run() {
calculate2();
}
});
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException ex) {
Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
}
Long end = System.currentTimeMillis();
System.out.println("Duration: " + (end - start));
System.out.println("List size: " + integerList.size());
}
}
public class App {
public static void main(String[] args) {
new ProcessSomething().process();
}
}
Все классы коллекций (кроме Vector и Hashtable) в пакете java.util не являются поточно-ориентированными. Только две старые коллекции являются поточно-ориентированными: Vector и Hashtable. ЗАЧЕМ? Вот причина: синхронизация может быть очень дорогой! Вы знаете, Vector и Hashtable - это две коллекции, которые существуют на ранних этапах истории Java, и они с самого начала созданы для поточной защиты (если у вас будет возможность взглянуть на их исходный код, вы увидите, что все их методы синхронизированы!). Однако они быстро показывают низкую производительность в многопоточных программах. Как вы, возможно, знаете, синхронизация требует блокировок, для мониторинга которых всегда требуется время, что снижает производительность. Вот почему новые коллекции (List, Set, Map и т.д.) Вообще не предусматривают управление параллелизмом для обеспечения максимальной производительности в однопоточных приложениях.
синхронизация снижает производительность. конечно, коллекция Java не синхронизирована. но Java предоставляет устройства синхронизации для синхронизации коллекции Java см. ссылку
for example:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class SynchronizedListExample {
public static void main(String[] args) {
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
syncList.add("one");//no need to synchronize here
syncList.add("two");
syncList.add("three");
String st = syncList.get(0); //it is ok here => no need to synchronize
// when iterating over a synchronized list, we need to synchronize access to the synchronized list
//because if you don't synchronize here, synchList maybe be changed during iterating over it
synchronized (syncList) {
Iterator<String> iterator = syncList.iterator();
while (iterator.hasNext()) {
System.out.println("item: " + iterator.next());
}
}
}
}
import java.util.Collections; // Импортируем это
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
Вот как вы можете синхронизировать список в Java.
Я предполагаю, что каждая реализация API коллекции написана в документации.