Исключения в фоновой задаче в Java
Проверка входных данных в фоне может обнаружить пустой
идентификатор. Исключение в рабочем потоке не всплывает
напрямую в main: его упаковывают в результат
ожидания, иначе терялась бы связь между потоками.
Если call() бросает ошибку, Future.get()
завершится ExecutionException. Исходная причина
лежит в getCause():
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(1);
Callable<String> risky = () -> {
throw new IllegalStateException("bad id");
};
Future<String> slot = pool.submit(risky);
pool.shutdown();
try {
slot.get();
} catch (ExecutionException ex) {
System.out.println(ex.getCause().getMessage());
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
На экране bad id. Перехватывают именно
ExecutionException при чтении Future,
а бизнес-ошибку разбирают через getCause().
Для Runnable без возвращаемого значения сбой
тоже проявится при get() после submit.
Необработанное исключение внутри execute может
попасть в стандартный обработчик пула; в прикладном коде
лучше оборачивать тело задачи в try/catch или
всегда использовать submit и проверять
Future.
invokeAll и invokeAny при провале задач
тоже сигнализируют через ExecutionException
или, если не осталось успешных попыток, через
ExecutionException с вложенными причинами.
Поставьте Callable, который бросает
IllegalArgumentException с текстом
"empty". Перехватите ExecutionException
и выведите сообщение причины.