Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 662
Frankie Avatar asked Aug 13 '18 09:08

Frankie


People also ask

How do you shut down an ExecutorService?

To properly shut down an ExecutorService, we have the shutdown() and shutdownNow() APIs. This method returns a list of tasks that are waiting to be processed. It is up to the developer to decide what to do with these tasks.

Should ExecutorService be shutdown?

An ExecutorService should be shut down once it is no longer needed to free up system resources and to allow graceful application shutdown. Because the threads in an ExecutorService may be nondaemon threads, they may prevent normal application termination.

Which of the following is a preferred way of shutdown executors?

Using shutdownNow() The shutdownNow() is a hard signal to destroy ExecutorService immediately along with stopping the execution of all in-progress and queued tasks. Use this method, when we want the application to stop processing all tasks immediately.

How do you turn off a ThreadPool?

The ThreadPool can be shutdown by calling the close() method. This will prevent the pool from accepting new tasks. Once all issued tasks are completed, the resources of the ThreadPool, such as the worker threads, will be released. Prevents any more tasks from being submitted to the pool.


2 Answers

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.
like image 89
Malt Avatar answered Oct 20 '22 08:10

Malt


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.

like image 20
Shivang Agarwal Avatar answered Oct 20 '22 06:10

Shivang Agarwal