简体   繁体   English

在Java中关闭ExecutorService的最佳方法

[英]Best way to shutdown ExecutorService in Java

I am trying to write asynchronous programming in Java and I am using ExecutorService to create a pool backed by several threads to submit multiple callable tasks but I have few questions about how to shutdown the ExecutorService. 我正在尝试用Java编写异步编程,我正在使用ExecutorService创建一个由多个线程支持的池来提交多个可调用任务,但我对如何关闭ExecutorService几乎没有疑问。

Here are my original codes: 这是我的原始代码:

ExecutorService executorService = Executors.newFixedThreadPool(10);

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

executorService.shutdown();

String result = f.get();
System.out.println(result);

This works good, and the executor shuts down after the threads are done. 这很好用,执行程序在线程完成后关闭。 But I am worried what if write something wrong the code in callable task f.get() takes forever and the program will halt forever and never exit. 但我担心如果写错了可调用任务f.get()的代码永远需要,程序将永远停止并永远不会退出。

With the worry, here is my second try: 有了担心,这是我的第二次尝试:

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);

With codes above, I can make sure threads are closed after 10 seconds. 使用上面的代码,我可以确保线程在10秒后关闭。 But actually the program is blocked for 10 seconds and thread may only use 5 seconds to be done. 但实际上程序被阻止了10秒,线程可能只用了5秒钟。

My question is how to set the time to force to close threads in pool so that I do not need to explicitly use awaitTermination to block the program. 我的问题是如何设置强制关闭池中的线程的时间,以便我不需要显式使用awaitTermination来阻止程序。

But I am worried what if write something wrong the code in callable task f.get() takes forever and the program will halt forever and never exit. 但我担心如果写错了可调用任务f.get()中的代码永远需要,程序将永远停止并永远不会退出。

That's a bug. 那是一个错误。 You need to make sure that doesn't happen. 你需要确保不会发生这种情况。

With codes above, I can make sure threads are closed after 10 seconds 使用上面的代码,我可以确保线程在10秒后关闭

No, you can't. 不,你不能。 Even shutdownNow() doesn't actually guarantee that the executor threads are shut down ( documentation ): 甚至shutdownNow()实际上并不保证执行程序线程被关闭( 文档 ):

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. 除尽力尝试停止处理主动执行任务之外,没有任何保证。 For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate. 例如,典型的实现将通过Thread.interrupt()取消,因此任何未能响应中断的任务都可能永远不会终止。

The ThreadPoolExecutor tries to "shut down now" by interrupting all worker threads. ThreadPoolExecutor试图通过中断所有工作线程来“立即关闭”。 You need to make sure that your tasks handle interrupts correctly . 您需要确保您的任务正确处理中断

Once your tasks stop correctly, you can estimate how long a shutdown should take based on your application and the tasks you're shutting down. 一旦您的任务正确停止,您就可以根据应用程序和正在关闭的任务来估计关闭所需的时间。 Then you can do a graceful shutdown: 然后你可以正常关机:

  • Call shutdown() 调用shutdown()
  • Wait for an orderly shutdown for a reasonable amount of time using awaitShutdown() 使用awaitShutdown()等待一段合理的时间有序关闭
  • If the executor is still running, call shutdownNow() and handle any outstanding tasks it returns. 如果执行程序仍在运行,请调用shutdownNow()并处理它返回的任何未完成的任务。

Your program should not blocked fro 10 second in your second version. 您的程序不应该在第二个版本中被阻止10秒。 It should wait for 10 seconds only if your threads does not terminate in 10 seconds. 只有当你的线程没有在10秒内终止时,它应该等待10秒。 Your executor service will suspend the termination of all the threads in case of your threads does not complete in 10 seconds. 如果您的线程在10秒内未完成,您的执行程序服务将暂停所有线程的终止。 From Java docs 来自Java文档

/** * Blocks until all tasks have completed execution after a shutdown * request, or the timeout occurs, or the current thread is * interrupted, whichever happens first. / ** *阻塞,直到所有任务在关闭*请求之后完成执行,或发生超时,或者当前线程被*中断,以先发生者为准。 * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return {@code true} if this executor terminated and * {@code false} if the timeout elapsed before termination * @throws InterruptedException if interrupted while waiting */ * * @param超时最长等待时间* @param单位超时参数的时间单位* @return {@code true}如果此执行程序终止,* {@code false}如果超时之前超时* @throws InterruptedException如果在等待时被打断* /

I would like to add below points in addition to the above answers. 除了上面的答案,我想补充以下几点。

You can call the isDone() method of Future api before calling the get() method to verify that if the task is done as you are waiting for the task to be done via awaitTermination method of ExcuterService api. 您可以在调用get()方法之前调用Future api的isDone()方法,以验证是否在通过ExcuterService api的awaitTermination方法等待任务完成时完成任务。

But What I would suggest instead of using awaitTermination and shutdownNow you can use 但是我建议使用awaitTermination和shutdownNow而不是使用

get(long timeout, TimeUnit unit) [Waits if necessary for at most the given time for the computation to complete, and then retrieves its result, if available.] get(long timeout,TimeUnit unit)[如果需要,最多在给定时间内等待计算完成,然后检索其结果(如果可用)。

of future API. 未来的API。 It will throw TimeoutException if the timeout occurs, you may try to call shutdownNow . 如果发生超时,它将抛出TimeoutException,您可能会尝试调用shutdownNow

you can also can check for shutdown status via isShutdown() method of ExecuterService API. 您还可以通过ExecuterService API的isShutdown()方法检查关闭状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM