Sobes.tech
Назад к вопросам
Junior — Middle
47

Какие компоненты из пакета concurrency вы применяли в своих проектах?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Важно показать, что есть практический опыт работы с java.util.concurrent, а не только знание названий классов. Обычно ждут понимания, когда использовать ExecutorService, Future, CountDownLatch, Semaphore, ConcurrentHashMap, BlockingQueue и чем они полезнее synchronized. Хороший ответ связывает конкретные компоненты с решаемыми задачами: параллельная обработка, синхронизация потоков, ограничение доступа к ресурсу, безопасный доступ к данным.

Определение:

Пакет concurrency в Java — это набор инструментов для многопоточности и параллельного выполнения задач. Он помогает безопасно запускать задачи в нескольких потоках, координировать их завершение, ограничивать конкуренцию за ресурсы и работать с потокобезопасными коллекциями. На практике чаще всего используют пул потоков, синхронизаторы и concurrent-коллекции.

Пример использования:

Например, в сервисе нужно обработать несколько независимых запросов параллельно и дождаться завершения всех. Для этого можно использовать ExecutorService для запуска задач, CountDownLatch для ожидания завершения и ConcurrentHashMap для безопасного накопления результатов.

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public class ConcurrencyExample {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(4);
        CountDownLatch latch = new CountDownLatch(3);
        Map<String, Integer> results = new ConcurrentHashMap<>();

        List<Callable<Void>> tasks = new ArrayList<>();
        tasks.add(() -> { results.put("a", 10); latch.countDown(); return null; });
        tasks.add(() -> { results.put("b", 20); latch.countDown(); return null; });
        tasks.add(() -> { results.put("c", 30); latch.countDown(); return null; });

        for (Callable<Void> task : tasks) {
            pool.submit(task);
        }

        latch.await();
        pool.shutdown();

        System.out.println(results);
    }
}

Пояснение кода:

Здесь ExecutorService управляет пулом потоков, поэтому не нужно создавать новый поток на каждую задачу. Каждая задача записывает результат в ConcurrentHashMap, который безопасен при одновременной записи из нескольких потоков. CountDownLatch инициализирован значением 3, потому что нужно дождаться трех задач; каждая задача вызывает countDown(), а основной поток блокируется на await(), пока счетчик не станет нулем. После завершения всех задач пул корректно закрывается через shutdown().

Ключевые моменты:

  • ExecutorService — базовый инструмент для запуска и управления задачами в пуле потоков.
  • Future нужен, когда требуется получить результат асинхронной задачи или дождаться ее завершения.
  • CountDownLatch, CyclicBarrier, Semaphore используют для синхронизации и координации потоков.
  • ConcurrentHashMap, BlockingQueue и другие concurrent-коллекции безопасны для многопоточного доступа.
  • synchronized подходит для простых случаев, но concurrency-инструменты удобнее и гибче для прикладных сценариев.
  • На собеседовании важно не перечислять классы, а объяснять, какую задачу каждый из них решал в проекте.