Подтвердить что ты не робот

Какие коллекции Java синхронизированы (потокобезопасны), а какие нет?

Какие коллекции Java синхронизированы, а какие нет?

Пример: HashSet не синхронизирован

4b9b3361

Ответ 1

Существует три группы коллекций.

  • Коллекция Java 1.0, которая в основном относится к устаревшим классам. Сюда входят Hashtable, Vector, Stack. Они синхронизированы, но я не рекомендую их использовать. Свойства - это, пожалуй, одно исключение, но я бы не использовал его в многопоточном контексте.
  • Сборники Java 1.2, добавленные в 1998 году, которые в значительной степени заменяют эту коллекцию, не синхронизированы, но могут быть синхронизированы с использованием методов Collections.synchronizedXxx()
  • Обновления Java 5.0 concurrency, добавленные в 2004 году, поддерживают блокировки, потокобезопасные коллекции.

Короче говоря, ни одна из коллекций, которые я бы рекомендовал вам использовать, синхронизирована.

Ответ 2

Вы можете получить синхронизированную версию Java Collection с

Collections.synchronizedCollection(Collection<T> c)

[javadoc]

Ответ 3

Простой ответ: ни одна реализация Collection не синхронизируется, потому что synchronized не является свойством класса, он применим только к методам и блокам.

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

Информация всегда включена в javadoc (как здесь: Arraylist - который не является потокобезопасным)

Ответ 4

Потокобезопасные Коллекции -

  1. ConcurrentHashMap

Потокобезопасен без синхронизации всей карты. Очень быстрое чтение, когда запись выполняется с блокировкой. Нет блокировки на уровне объекта. Использует множество блокировок.

  1. SynchronizedHashMap

Синхронизация на уровне объекта. И чтение, и запись получают блокировку. Блокировка коллекции имеет недостаток производительности. Может вызвать конфликт

  1. Вектор

  2. Хеш-таблица

  3. CopyOnWriteArrayList

  4. CopyOnWriteArraySet

  5. стек

Остальные все не нить безопасны

Ответ 5

ArrayList, LinkedList, HashSet, LinkedHashset и TreeSet в интерфейсе коллекции и HashMap, LinkedHashMap и Treemap являются несинхронизированными.

Вектор в интерфейсе коллекции Синхронизированный

Ответ 6

Предыдущий пример совершенно неправильный.

Прежде всего, вы не получаете доступ из разных потоков списка, который вы только что синхронизировали, вы не можете доказать, что синхронизация выполняется правильно, вы не можете доказать, что процесс добавления является атомарным. Во-вторых, синхронизированное предложение по самому списку является плохой практикой, вы не знаете, будет ли оптимизатор использовать элемент в списке для синхронизации, что приведет к неожиданному поведению. Кроме того, синхронизация - это доступ к элементам в списке чтения/записи, а не к самому списку. Выньте 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();
    }
}

Ответ 7

Все классы коллекций (кроме Vector и Hashtable) в пакете java.util не являются поточно-ориентированными. Только две старые коллекции являются поточно-ориентированными: Vector и Hashtable. ЗАЧЕМ? Вот причина: синхронизация может быть очень дорогой! Вы знаете, Vector и Hashtable - это две коллекции, которые существуют на ранних этапах истории Java, и они с самого начала созданы для поточной защиты (если у вас будет возможность взглянуть на их исходный код, вы увидите, что все их методы синхронизированы!). Однако они быстро показывают низкую производительность в многопоточных программах. Как вы, возможно, знаете, синхронизация требует блокировок, для мониторинга которых всегда требуется время, что снижает производительность. Вот почему новые коллекции (List, Set, Map и т.д.) Вообще не предусматривают управление параллелизмом для обеспечения максимальной производительности в однопоточных приложениях.

Ответ 8

синхронизация снижает производительность. конечно, коллекция 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());
                }
            }

        }

    }

Ответ 9

import java.util.Collections; // Импортируем это

List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

Вот как вы можете синхронизировать список в Java.

Ответ 10

Я предполагаю, что каждая реализация API коллекции написана в документации.