Best way to shutdown ExecutorService in Java
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.
When the executorService.shutdown(); should be called
There are two flavors of threads in Java (of course depending on how you look at them). 'User' threads and 'Daemon' threads. You application ends in one of the following cases:
- You call
System.exit()
- You have no
User
threads left in your application. This is explained here.
Note that your main
function is executed by the JVM on a 'User' thread, meaning that as long as you have not completed your main
function. Most multithreaded applications will run the main function only to start all the threads needed.
The idea behind Daemon threads is that you can do something (regularly), but if all other tasks are done, it will not prevent the application from exiting.
By default new threads are 'Non Daemon' threads, the same goes for the threads craeted by your ExecutorService
. If you want to change this, you have to create your own ThreadFactory
. A ThreadFactory
allows you to manually create the threads for your ExecutorService, it will be called when the ExecutorService
needs a new thread. Here is an example of one that created 'Daemon' threads:
public class DaemonThreadFactory implements ThreadFactory
{
@Override
public Thread newThread(final Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
This can then be used by creating the executor service:
ExecutorService service = Executors.newFixedThreadPool(100, new DaemonThreadFactory());
Note that this is also the way to give your threads custom names, which is very useful as many logframeworks log the thread name (and the debugger shows it).
If you were to do this, in your application, it would exit right away, because you only create 'Daemon' threads, so you would have to either keep another thread alive (this could be done implicitly by another framework, for instance if you have GUI).
An alternative is to manually call System.exit()
. Normally calling System.exit()
in your code is not recommended. Mostly because it does not allow for good refactoring, reusing, testing and many exit points make your application unpredictable. In order to circumvent these problems, you could create a callback function that handles the job complete event. In this application you call System.exit()
, your test code or other applications could do something else.
Related Topics
Read Rsa Private Key of Format Pkcs1 in Java
How to Upper Case Every First Letter of Word in a String
Java Bigdecimal: Round to the Nearest Whole Value
How to Find Out If "Debug Mode" Is Enabled
How to Escape the Equals Sign in Properties Files
Java.Lang.Noclassdeffounderror: Org.Slf4J.Loggerfactory
Minimum Spring Version Compatible with Java 11
How to Get Start and End Range from List of Timestamps
How to Use Classloader.Getresources() Correctly
Can an Interface Extend Multiple Interfaces in Java
How to Dynamically Create a Test Suite in Junit 4
Execute Jar File with Multiple Classpath Libraries from Command Prompt
How to Use 3Rd Party Library in Java9 Module
Performance Difference Between Java 8 Lambdas and Anonymous Inner Classes