Какие типы задач принимает на выполнение ExecutorService в Java?

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

Ответ

ExecutorService принимает задачи, представленные в виде объектов, реализующих интерфейсы Runnable или Callable<T>.

Интерфейс Возвращает результат? Может бросать проверяемые исключения? Метод отправки в ExecutorService
Runnable Нет Нет execute(Runnable) или submit(Runnable)
Callable<T> Да (Future<T>) Да submit(Callable<T>)

Почему два интерфейса? Runnable — для простых фоновых задач, Callable — когда нужен результат вычислений или обработка исключений.

Пример:

ExecutorService executor = Executors.newFixedThreadPool(2);

// Задача Runnable (без результата)
executor.execute(() -> {
    System.out.println("Выполняю фоновую задачу");
});

// Задача Callable (с результатом)
Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "Результат вычисления";
});

// Получение результата из Future (блокирующий вызов)
String result = future.get();
System.out.println(result);

// Обязательно завершаем сервис
 executor.shutdown();