How to Shutdown an Executorservice

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:

  1. You call System.exit()
  2. 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



Leave a reply



Submit