java.util.concurrent: карта инструментов

Исполнение задач

НуждаИнструмент
ограниченный пул CPU-задачThreadPoolExecutor / fixed pool
задачи по расписаниюScheduledExecutorService
рекурсивное CPU-разбиениеForkJoinPool
результат одной задачиОбъект Future
цепочка и объединение результатовCompletableFuture

Executor нужно завершать:

executor.shutdown();
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
    List<Runnable> notStarted = executor.shutdownNow();
}

shutdownNow() пытается interrupt-нуть выполняющиеся задачи, но не гарантирует их остановку.

Защита состояния

  • Lock, ReadWriteLock, StampedLock;
  • Atomic*, LongAdder;
  • ConcurrentHashMap, ConcurrentLinkedQueue;
  • CopyOnWriteArrayList для редких записей.

Передача и координация

  • BlockingQueue — producer/consumer и backpressure;
  • CountDownLatch, CyclicBarrier, Phaser — Синхронизаторы;
  • Semaphore — лимит параллелизма;
  • Condition — несколько wait set у одного Lock;
  • Exchanger — парный обмен.

Как выбрать пул

Для CPU-bound работы число активных потоков обычно близко к числу ядер. Для блокирующей нагрузки допустимо больше, но предел задают память, очередь, connection pool и внешний сервис. Неограниченная очередь скрывает перегрузку ростом latency; bounded queue требует явной rejection policy.

ThreadPoolExecutor pool = new ThreadPoolExecutor(
        8, 8,
        0, TimeUnit.MILLISECONDS,
        new ArrayBlockingQueue<>(500),
        new ThreadPoolExecutor.CallerRunsPolicy()
);

CallerRunsPolicy замедляет производителя, но ее влияние на request thread нужно оценивать.

На собеседовании

  • Разница execute и submit? submit возвращает Future и захватывает ошибку задачи; execute — нет.
  • Что происходит после shutdown? Новые задачи отвергаются, принятые выполняются.
  • Почему bounded queue важна? Ограничивает память и делает перегрузку наблюдаемой.
  • Чем LongAdder отличается от AtomicLong? Лучше масштабирует конкурентные прибавления, но sum() не является атомарным snapshot относительно обновлений.
  • Гарантирует ли shutdownNow остановку? Нет.