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();
}
}
The shutdown () method doesn't cause immediate destruction of the ExecutorService. It will make the ExecutorService stop accepting new tasks and shut down after all running threads finish their current work:
ExecutorService interface provides 3 methods shutdown (), shutdownNow () and awaitTermination () for controlling the termination of tasks submitted to executor. Learn to use these methods under different requirements. 1. Difference between shutdown (), shutdownNow () and awaitTermination () APIs
In general, the ExecutorService will not be automatically destroyed when there is not task to process. It will stay alive and wait for new tasks to do. It simply means that JVM will not terminate if we are expecting it to be.
Another interesting scenario is when you have a ScheduledExecutorService that performs a periodic task. The only way to stop the chain of periodic tasks is to call shutdown (). EDIT: I'd like to add that I wouldn't recommend using a shutdown hook as shown above in the general case: it can be error-prone and should be a last resort only.
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.
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:
System.exit()
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.
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