简体   繁体   中英

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.

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.

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. But actually the program is blocked for 10 seconds and thread may only use 5 seconds to be done.

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.

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.

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

No, you can't. Even shutdownNow() doesn't actually guarantee that the executor threads are shut down ( documentation ):

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.

The ThreadPoolExecutor tries to "shut down now" by interrupting all worker threads. 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()
  • Wait for an orderly shutdown for a reasonable amount of time using awaitShutdown()
  • If the executor is still running, call shutdownNow() and handle any outstanding tasks it returns.

Your program should not blocked fro 10 second in your second version. It should wait for 10 seconds only if your threads does not terminate in 10 seconds. Your executor service will suspend the termination of all the threads in case of your threads does not complete in 10 seconds. From Java docs

/** * 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 */

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.

But What I would suggest instead of using awaitTermination and shutdownNow you can use

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.]

of future API. It will throw TimeoutException if the timeout occurs, you may try to call shutdownNow .

you can also can check for shutdown status via isShutdown() method of ExecuterService API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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