5

We have a service method GetDataParallel( ) which maybe called by many clients currently, and we use the ExecutorService to called the MyCallable inside it. However I found unless I called the executorService.shutdown(); the application never exit, so why the application cannot exit , we must shut down all thread pool threads manually before the application exit? and in service environment I think we don't need to call the executorService.shutdown(); to keep the application alive, right ?

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreading {

    static ExecutorService executorService = Executors.newFixedThreadPool(100);
    private List<String> _BusinessUnits= new ArrayList<String>();
    public static void main(String[] args) throws Exception {

        MultiThreading  kl =new MultiThreading();
        kl.GetDataParallel();
        Thread.sleep(10000);
        System.out.println("111111111");
         //executorService.shutdown();

    }

    public   void GetDataParallel( ) throws Exception
    {
        _BusinessUnits.add("BU1");
        _BusinessUnits.add("BU2");
        _BusinessUnits.add("BU3");

        for(final String v : _BusinessUnits)
        {
            ExecutorServiceTest.executorService.submit( new MyCallable());
        }
    }
}

  class MyCallable implements Callable  {
    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        //return the thread name executing this callable task
        System.out.println(Thread.currentThread().getName());
        return Thread.currentThread().getName();
    }
}
Jason
  • 1,115
  • 14
  • 25
  • Executor threads are not daemon threads and therefore the JVM will not terminate while they are running. You have to shut them down manually. http://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java I suppose you could use a custom ThreadFactory that provided daemon threads, but shutdown is a lot more straightforward and cleaner, and safer especially if you're doing io in your tasks. – Jason C Aug 30 '16 at 05:45
  • @Jason C , what's the meaning " while they are running. " ? running mean the thread executing the code or they are just stay in thread pool? You know the thread finished run the callable after 1 seconds, so it shouldn't be in the running status after 1 second, however the application still didn't exit after much times. – Jason Aug 30 '16 at 05:54
  • If they're active, in the thread pool. Not necessarily executing tasks. E.g. the threads in a fixed thread pool are always running even if the queue is empty. The threads in a cached thread pool will eventually idle out and die if there are no tasks. Calling shutdown will terminate the threads. – Jason C Aug 30 '16 at 05:57
  • @Jason C , do you think the custom ThreadFactory with daemon threads, or ExecutorService without daemon threads is more suitable for the service environment? If we use the ExecutorService , it seems we cannot call the shutdown , otherwise no other clients can call the service , right? – Jason Aug 30 '16 at 06:02
  • Also the Executors.newFixedThreadPool(100); would created the 100 threads right away, instead of starting from 0 , and add more threads to the thread pool when more tasks need to execute? – Jason Aug 30 '16 at 06:08
  • @Jason C, "but shutdown is a lot more straightforward and cleaner, and safer especially if you're doing io in your tasks" , which place \when we call the shutdown ? In a service environment, if we declare the Executor in the class level, and called the shutdown when we called the service method, then threads in the thread pool cannot be reused by the other clients. – Jason Aug 30 '16 at 06:12
  • Depends on what you mean by "service environment". For example, with Tomcat, a good place to do it would be [in response to the context being destroyed](http://stackoverflow.com/questions/12815614/shutdown-executorservice-gracefully-in-webapp). – Jason C Aug 30 '16 at 07:04
  • And no `newFixedThreadPool(100)` would not create 100 threads immediately. It creates them on first use, up to 100 max, and then they stay running, even if they go back to idle, until `shutdown()` is called (or until one terminates abnormally, in which case it is replaced by a new one). – Jason C Aug 30 '16 at 07:10

4 Answers4

5

Typically you shut down an ExecutorService when the application is exiting - most applications have some sort of lifecycle and shutdown sequence. If you expect your application to exit when the main thread completes whatever it has to do, you want to shut it down when its work is done (meaning there's a well-defined point at which it's work is done, and you can tell when that is).

Server-side frameworks frequently have lifecycle methods that you can hook into to detect when your code is being shut down and cleanly exit. Or you can use VM shutdown hooks (perhaps to delay shutdown until all currently queued jobs are complete), so that no matter what code causes the program to exit, your cleanup code will be run.

In general, it's a good idea to create a well-defined exit point if there isn't one provided by a framework - it lets you have an application that can be cleanly unloaded (and perhaps, reloaded with updated configuration) without the VM necessarily shutting down at all - I've used that trick to be able to have a server application reconfigure itself and reload with zero downtime in response to a Unix signal.

So, the simple answer to your question is "When it isn't going to be used anymore". In almost any application there is a point at which that's unambiguously true.

BTW, to contradict one of the other responders, an ExecutorService can use daemon threads - you can provide a ThreadFactory that configures threads however you want before you start them. But I'd encourage you to not use daemon threads and explicitly shut down the thread pool at a well-defined point - that's not the typical practice, but it will both mean your code has the potential to be shut down cleanly, and it will encourage you to think about lifecycle, which is likely to lead to better code.

Tim Boudreau
  • 1,741
  • 11
  • 13
  • 1
    Well explained @Tim. – CuriousMind Aug 30 '16 at 07:07
  • "If you expect your application to exit when the main thread completes whatever it has to do, you want to shut it down when its work is done" well said :) – Ravindra babu Sep 01 '16 at 13:47
  • My app uses a class that implements the MessageListener interface, when should I shut my ExecutorService down? I initialized the context/executor in a servlet and then store the them in their own static variable that can be accessed by the onMessage event. I then execute the executor in the onMessage method/event. So everytime a message is received, it will use one thread. But where should I place the shutdown method? Putting it at the end of the onMessage message will make it reject new tasks. Should I even shutdown my executor? – Wax Jun 02 '17 at 07:06
4

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.

Thirler
  • 20,239
  • 14
  • 63
  • 92
  • If all of the 100 threads hang and not return, it mean there is no thread can service the new request, in that case, can we force abort the hang thread? Or if there is a timeout setting and after the timeout the hang thread would be exit\abort and return the thread pool automatically. Or there is other good suggestion to deal with the hang threads? – Jason Aug 30 '16 at 12:42
  • @Jason There is no nice way to abort a really stuck thread (if you want to know more, read why `Thread.stop()` has been deprecated). You can make your tasks interruptable (meaning they have to check the `Thread.interrupted()` flag and handle the `InterruptedException` gracefully. – Thirler Aug 30 '16 at 15:15
1

In application environment, you must call shutdown to ensure threads launched by ExecutorService must stop and it should not accept any more new tasks. Otherwise JVM will not exit.

In case of Service, you should call shutdown prior to stopping your Service execution. For e.g. in case of web-app, the contextDestroyed method of ServletContextListener is useful to invoke shutdown method of ExecutorService. This will ensure that any existing tasks must be completed prior to abrupt termination of application, but no new task will be accepted for processing.

CuriousMind
  • 3,143
  • 3
  • 29
  • 54
  • ,In case of Service,the custom ThreadFactory with daemon threads, or ExecutorService without daemon threads ,which one is more suitable? Or it totally depends on? – Jason Aug 30 '16 at 06:53
  • ThreadFactory is meant for avoiding calls to `new Thread` and clutter the code. Also more useful to name the threads and set priorities etc. In case of Service, use ExecutorService, when you want to control number of concurrent threads (but their name and priorities don't make difference). – CuriousMind Aug 30 '16 at 07:04
1

However I found unless I called the executorService.shutdown(); the application never exit,

I think we don't need to call the executorService.shutdown(); to keep the application alive, right ?

Yes. Application is alive unless you call executorService.shutdown()

Every application should have an exit point. You can call shutdown during that exit point.

If you don't have any known exit points, ShutdownHook is one way to address your problem. But you should be aware that

In rare circumstances the virtual machine may abort, that is, stop running without shutting down cleanly

For the example you have quoted, you can address it in multiple ways (invokeAll, Future.get(), CountDownLatch etc). Have a look at related SE question.

ExecutorService, how to wait for all tasks to finish

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211