Какую потокобезопасную коллекцию в Java выбрать при частых операциях чтения?

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

Ответ

Для сценария «частое чтение, редкая запись» оптимальным выбором является CopyOnWriteArrayList (для списков) или ConcurrentHashMap (для ассоциативных массивов).

CopyOnWriteArrayList:

  • Принцип: При каждой модификации (add, set) создается новая копия внутреннего массива. Чтение происходит из неизменяемого «снимка» (snapshot) без блокировок.
  • Плюсы: Идеальная производительность чтения, полная потокобезопасность.
  • Минусы: Дорогая операция записи, потребление памяти при модификациях.
  • Применение: Списки слушателей (listeners), rarely-updated конфигурации.
CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<>();
// Чтение — быстрое и без блокировок
for (String item : threadSafeList) { 
    System.out.println(item);
}
// Запись — создает новую копию массива
threadSafeList.add("new element");

ConcurrentHashMap:

  • Принцип: Использует сегментирование блокировок (в современных версиях — lock-striping и CAS-операции).
  • Плюсы: Высокая производительность как для чтения (неблокирующее), так и для конкурентных записей.
  • Применение: Универсальная потокобезопасная мапа для кэшей, хранилищ состояний.

Вывод: Для списков с преобладанием чтения — CopyOnWriteArrayList. Для пар ключ-значение — ConcurrentHashMap.