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.
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.
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.
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.
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.
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:
shutdown()
awaitShutdown()
shutdownNow()
and handle any outstanding tasks it returns.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With