在Java中关闭ExecutorService的最佳方法

Fra*_*kie 5 java multithreading

我正在尝试用Java编写异步编程,我正在使用ExecutorService创建一个由多个线程支持的池来提交多个可调用任务,但我对如何关闭ExecutorService几乎没有疑问.

这是我的原始代码:

ExecutorService executorService = Executors.newFixedThreadPool(10);

Future<String> f = executorService.submit(() -> {/*do something*/});

executorService.shutdown();

String result = f.get();
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

这很好用,执行程序在线程完成后关闭.但我很担心如果写出错误的话,可调用任务中的代码 f.get()将永远占用,程序将永远停止并永不退出.

有了担心,这是我的第二次尝试:

ExecutorService executorService = Executors.newFixedThreadPool(10);

Future<String> f = executorService.submit(() -> {/*do something*/});

executorService.shutdown();

if(!executorService.awaitTermination(10, TimeUnit.SECONDS)){
    executorService.shutdownNow();
}

String result = f.get();
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,我可以确保线程在10秒后关闭.但实际上程序被阻止了10秒,线程可能只用了5秒钟.

我的问题是如何设置强制关闭池中的线程的时间,以便我不需要显式使用awaitTermination来阻止程序.

Mal*_*alt 5

但我担心如果写错了可调用任务f.get()中的代码永远需要,程序将永远停止并永远不会退出.

那是一个错误.你需要确保不会发生这种情况.

使用上面的代码,我可以确保线程在10秒后关闭

不,你不能.甚至shutdownNow()实际上并不保证执行程序线程被关闭(文档):

除尽力尝试停止处理主动执行任务之外,没有任何保证.例如,典型的实现将通过Thread.interrupt()取消,因此任何未能响应中断的任务都可能永远不会终止.

在ThreadPoolExecutor试图通过中断所有工作线程"现在关机".您需要确保您的任务正确处理中断.

一旦您的任务正确停止,您就可以根据应用程序和正在关闭的任务来估计关闭所需的时间.然后你可以正常关机:

  • 呼叫 shutdown()
  • 等待一段时间的有序关机 awaitShutdown()
  • 如果执行程序仍在运行,请调用shutdownNow()并处理它返回的任何未完成的任务.