Каков ваш опыт работы с многопоточностью в Java?

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

Ответ

Да, работал. Основные инструменты: Thread, Runnable, ExecutorService, synchronized, volatile, Lock, Concurrent Collections.

Почему это важно: Прямая работа с Thread дает понимание основ, но в production-коде предпочтительнее высокоуровневые API, такие как ExecutorService, которые управляют пулами потоков, экономя ресурсы и упрощая масштабирование.

Пример с ExecutorService:

ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
    executor.submit(() -> {
        System.out.println(Thread.currentThread().getName());
    });
}
executor.shutdown();

Практика синхронизации: Для явного контроля над блокировками вместо synchronized часто используется ReentrantLock, который предоставляет больше гибкости (например, попытку захвата с таймаутом).

Lock lock = new ReentrantLock();
lock.lock();
try {
    // критическая секция
} finally {
    lock.unlock(); // Гарантированное освобождение в finally
}

Современные подходы:

  • CompletableFuture — для композиции асинхронных операций и неблокирующего программирования.
  • ThreadLocal — для изолированного хранения данных в рамках одного потока (например, контекст пользователя в веб-запросе).