3

这里有一个再现:

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();
}
4

1 回答 1

4

总是很难找到一个很好的例子try-finally及其适当的用法。我认为是这样。

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

抛出的异常f.get();没有处理,主线程失败。ExecutorService但是该应用程序仍然包含您无法直接访问的非守护线程。

于 2018-11-11T17:45:23.520 回答