Какие concurrent collections в Java ты использовал и в чём их особенности?

«Какие concurrent collections в Java ты использовал и в чём их особенности?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Concurrent Collections из пакета java.util.concurrent предоставляют потокобезопасные реализации стандартных интерфейсов коллекций, оптимизированные для многопоточного доступа.

Основные классы и их применение:

  1. ConcurrentHashMap<K, V>

    • Особенность: Вместо блокировки всей таблицы использует блокировку на уровне сегментов (бакетов) или CAS-операции (в Java 8+).
    • Итераторы: Обход происходит с weak consistency — могут не отражать последние изменения, но не выбросят ConcurrentModificationException.
    • Пример:
      ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
      // Атомарные операции
      map.putIfAbsent("key", 1);
      map.compute("key", (k, v) -> v == null ? 1 : v + 1); // атомарное обновление
  2. CopyOnWriteArrayList<E> и CopyOnWriteArraySet<E>

    • Особенность: При каждой модификации (add, set) создаётся новая копия внутреннего массива. Дорогая запись, дешёвое чтение.
    • Использование: Идеально для сценариев, где чтение происходит на порядки чаще, чем запись (например, список слушателей events).
  3. ConcurrentLinkedQueue<E>

    • Особенность: Неблокирующая (lock-free) очередь на основе алгоритма Michael & Scott. Использует CAS.
    • Особенность итератора: Также weak consistency.
  4. BlockingQueue интерфейс и его реализации (ArrayBlockingQueue, LinkedBlockingQueue)

    • Особенность: Предоставляет блокирующие операции put() (ждёт, если очередь полна) и take() (ждёт, если очередь пуста). Основа для паттерна Producer-Consumer.

Ключевое отличие от Collections.synchronizedMap(): ConcurrentHashMap обеспечивает лучшую производительность при конкурентном чтении и записи за счёт finer-grained locking, в то время как синхронизированная версия блокирует всю коллекцию на время любой операции.