Будущее <T>.get () застревает, когда runnable выдает исключение - при работе на отдельной службе исполнителя? - PullRequest
0 голосов
/ 11 ноября 2018

Репродукция здесь:

import java.util.concurrent.*;

public class Main {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("Hello!");

        ExecutorService exec = Executors.newSingleThreadExecutor();

        Future<Integer> f = exec.submit(() -> x());

        f.get();

        System.out.println("f.get() returned");

        exec.shutdownNow();

        System.out.println("Good bye!");
    }

    private static Integer x() {
        throw new RuntimeException("An unfortunate event");
    }
}

Вывод показывает только "Привет!" и исключение трассировки стека, затем программа зависает навсегда.

Изменения, приведенные ниже, обходят проблему, но есть ли идея, почему выполнение зависает в приведенном выше коде?

Использование общего пула потоков НЕ зависает:

Future<Integer> f = ForkJoinPool.commonPool().submit(() -> x());

Завершение вызова вокруг try / catch позволяет приложению нормально завершиться:

Future<Integer> f = exec.submit(() -> x());

try {
    f.get();
} catch (Exception ex) {
    ex.printStackTrace();
}

1 Ответ

0 голосов
/ 11 ноября 2018

Всегда трудно найти хороший пример try-finally и его правильное использование. Я думаю, что это так.

try {
    f.get();
    System.out.println("f.get() returned");
} finally {
    exec.shutdownNow();
}

Исключение, выброшенное из f.get();, не обработано, основной поток завершился неудачно. Но приложение по-прежнему содержит потоки, не являющиеся демонами, управляемые ExecutorService, к которым у вас нет прямого доступа.

...