为了账号安全,请及时绑定邮箱和手机立即绑定

在 Java 中关闭 ExecutorService 的最佳方法

在 Java 中关闭 ExecutorService 的最佳方法

慕码人2483693 2021-07-09 18:37:54
我正在尝试用 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);这很好用,执行程序在线程完成后关闭。但是我担心如果写错了可调用任务中的代码 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);使用上面的代码,我可以确保线程在 10 秒后关闭。但实际上程序被阻塞了 10 秒,线程可能只用了 5 秒就可以完成。我的问题是如何设置强制关闭池中线程的时间,以便我不需要显式使用awaitTermination来阻止程序。
查看完整描述

3 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

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

那是一个错误。你需要确保这不会发生。

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

不,你不能。即使shutdownNow()实际上并不能保证执行程序线程已关闭(文档):

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

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

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

  • 称呼 shutdown()

  • 等待有序关闭一段合理的时间使用 awaitShutdown()

  • 如果执行程序仍在运行,则调用shutdownNow()并处理它返回的任何未完成任务。


查看完整回答
反对 回复 2021-07-14
?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

除了上述答案之外,我还想补充以下几点。

您可以在调用 get() 方法之前调用 Future api的isDone()方法来验证任务是否完成,因为您正在通过 ExcuterService api 的 awaitTermination 方法等待任务完成。

但是我建议你不要使用 awaitTermination 和 shutdownNow 你可以使用

get(long timeout, TimeUnit unit) [如有必要,最多等待给定的计算完成时间,然后检索其结果(如果可用)。]

未来的 API。如果发生超时,它将抛出 TimeoutException ,您可以尝试调用 shutdownNow

您还可以通过ExecuterService API 的isShutdown()方法检查关闭状态。


查看完整回答
反对 回复 2021-07-14
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

您的程序不应在第二个版本中阻塞 10 秒。仅当您的线程未在 10 秒内终止时,它才应等待 10 秒。如果您的线程未在 10 秒内完成,您的执行程序服务将暂停所有线程的终止。来自 Java 文档

/** * 阻塞直到所有任务在关闭请求后完成执行,或者超时发生,或者当前线程被中断,以先发生者为准。* * @param timeout 等待的最长时间 * @param unit 超时参数的时间单位 * @return {@code true} 如果此执行程序终止 * {@code false} 如果在终止之前超时 * @throws InterruptedException如果在等待时中断 */


查看完整回答
反对 回复 2021-07-14
  • 3 回答
  • 0 关注
  • 340 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信