ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку

Выбор между submit и execute в ExecutorService Java

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если вам требуется контролировать результат выполнения задачи через объект Future, то следует использовать метод submit. Он поможет получать результаты работы или отменять задачу. Метод execute идеально подойдет для задач, у которых нет необходимости в отслеживании результата:

  • submit:
Java
Скопировать код
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> "результат");
  • execute:
Java
Скопировать код
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> System.out.println("Задача выполнена!"));

Подводя итог: используйте submit для возможности контроля, и execute для простоты выполнения задач без отслеживания результата.

Пройдите тест и узнайте подходит ли вам сфера IT
Пройти тест

Понимание обработки исключений

Исключения в потоке работы метода execute перехватываются UncaughtExceptionHandler. В случае с submit, любые исключения захватываются объектом Future и преобразуются в ExecutionException, когда вы пытаетесь получить результат:

Java
Скопировать код
try {
    Future<?> future = executor.submit(() -> { throw new RuntimeException("Упс, ошибка выполнения!"); });
    future.get();
} catch (ExecutionException ee) {
    Throwable originalCause = ee.getCause();
}

Выбор подходящих задач

Метод execute работает с объектами Runnable, а submit может также принимать Callable. Это особенно актуально, когда задаче нужно возвращать результат или выбрасывать исключение:

Java
Скопировать код
Callable<Integer> task = () -> 1 + 1;
Future<Integer> future = executor.submit(task);

Осознанный выбор

Если вам не нужно знать о результатах работы задачи, и достаточно просто её выполнить, выбирайте execute. Если требуется более сложная логика управления задачами, включая отслеживание, отмену или обработку исключений, используйте submit.

Более полный контроль через переопределение

Можно расширить функционал, создав класс CustomThreadPoolExecutor и переопределив метод afterExecute для дополнительного контроля выполнения задачи:

Java
Скопировать код
public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        // Обработка исключений и других задач после выполнения
    }
}

Визуализация

Если представить ExecutorService как дирижёра оркестра:

Java
Скопировать код
ExecutorService orchestra = Executors.newFixedThreadPool(4);

Использование execute():

Java
Скопировать код
orchestra.execute(new Violinist());

🎻 Музыкант начинает играть, и не ждет аплодисментов.

Использование submit():

Java
Скопировать код
Future<String> applause = orchestra.submit(new Violist());

🎻👏 Музыкант играет и ожидает аплодисментов.

Какой итог вы хотите получить от "исполнения" вашей задачи, исходя из этого, и выбирайте подходящий метод.

Практические примеры использования

Запуск задач без затруднений

Используйте метод submit с обёртками, чтобы предотвратить возможные трудности с выполнением вашей задачи:

Java
Скопировать код
executor.submit(new NonBlockingTaskWrapper<>(() -> { /* body task */ }));

Обработка пользовательских запросов

ExecutorService пригодится при работе с динамическими задачами, особенно если вам нужно обрабатывать пользовательские запросы.

Оптимизация логирования ошибок

Создание класса ExtendedExecutor с переопределением методов позволяет эффективно упорядочить обработку ошибок и оптимизировать процесс логирования.

Полезные материалы

  1. Вопрос на Stack Overflow о блокировке в ThreadPoolExecutor — анализ различий между submit и execute.
  2. Руководство по ExecutorService от Oracle — пошаговое объяснение работы с ExecutorService.
  3. Общий обзор параллелизма в Java — обзор утилит для параллельной обработки данных в Java.
  4. Документация по ExecutorService — официальная документация Java SE.
  5. Выбор способа обработки многопоточности в Java — обсуждается выбор стратегий для многопоточности, что может помочь при принятии решения между submit и execute.