Какие основные инструменты предоставляет Java Concurrency API?

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

Ответ

Пакет java.util.concurrent предлагает высокоуровневые инструменты для многопоточности:

1. Executor Framework (Управление пулами потоков)

Заменяет прямое создание потоков (new Thread()).

ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> System.out.println("Task executed by " + Thread.currentThread().getName()));
executor.shutdown();

2. Асинхронные задачи с результатом

  • Callable<V> — аналог Runnable, но возвращает значение.
  • Future<V> — представляет результат асинхронной задачи.
    Future<Integer> future = executor.submit(() -> {
    Thread.sleep(1000);
    return 42;
    });
    Integer result = future.get(); // Блокирующий вызов, ждет результат

3. Более совершенные Future: CompletableFuture (Java 8+)

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

CompletableFuture.supplyAsync(() -> "Hello")
                 .thenApply(s -> s + " World")
                 .thenAccept(System.out::println); // Hello World

4. Синхронизаторы высокого уровня

  • CountDownLatch — ожидает, пока набор операций не завершится.
  • CyclicBarrier — точка синхронизации, где потоки ждут друг друга.
  • Semaphore — ограничивает количество потоков, имеющих доступ к ресурсу.
  • Phaser — гибкий, многоразовый барьер.

5. Потокобезопасные коллекции

ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue и др.

6. Усовершенствованные механизмы блокировок

  • ReentrantLock — расширяемая альтернатива synchronized (честность, таймауты, условные переменные).
  • ReentrantReadWriteLock — разделяет блокировки для чтения и записи.

7. Атомарные переменные

Классы типа AtomicInteger, AtomicReference обеспечивают потокобезопасные операции (инкремент, сравнение-и-замена/CAS) без явных блокировок.

AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // Потокобезопасно