[英]Best way to shutdown ExecutorService in Java
我正在尝试用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
来阻止程序。
但我担心如果写错了可调用任务f.get()中的代码永远需要,程序将永远停止并永远不会退出。
那是一个错误。 你需要确保不会发生这种情况。
使用上面的代码,我可以确保线程在10秒后关闭
不,你不能。 甚至shutdownNow()
实际上并不保证执行程序线程被关闭( 文档 ):
除尽力尝试停止处理主动执行任务之外,没有任何保证。 例如,典型的实现将通过Thread.interrupt()取消,因此任何未能响应中断的任务都可能永远不会终止。
ThreadPoolExecutor
试图通过中断所有工作线程来“立即关闭”。 您需要确保您的任务正确处理中断 。
一旦您的任务正确停止,您就可以根据应用程序和正在关闭的任务来估计关闭所需的时间。 然后你可以正常关机:
shutdown()
awaitShutdown()
等待一段合理的时间有序关闭 shutdownNow()
并处理它返回的任何未完成的任务。 您的程序不应该在第二个版本中被阻止10秒。 只有当你的线程没有在10秒内终止时,它应该等待10秒。 如果您的线程在10秒内未完成,您的执行程序服务将暂停所有线程的终止。 来自Java文档
/ ** *阻塞,直到所有任务在关闭*请求之后完成执行,或发生超时,或者当前线程被*中断,以先发生者为准。 * * @param超时最长等待时间* @param单位超时参数的时间单位* @return {@code true}如果此执行程序终止,* {@code false}如果超时之前超时* @throws InterruptedException如果在等待时被打断* /
除了上面的答案,我想补充以下几点。
您可以在调用get()方法之前调用Future api的isDone()方法,以验证是否在通过ExcuterService api的awaitTermination方法等待任务完成时完成任务。
但是我建议使用awaitTermination和shutdownNow而不是使用
get(long timeout,TimeUnit unit)[如果需要,最多在给定时间内等待计算完成,然后检索其结果(如果可用)。
未来的API。 如果发生超时,它将抛出TimeoutException,您可能会尝试调用shutdownNow 。
您还可以通过ExecuterService API的isShutdown()方法检查关闭状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.