Recently done a Web project, after discovering shutdown.sh, cannot shut down the tomcat process.
Ps-ef | grep Tomcat
The return tomcat process still exists. The investigation found that because the thread pool was started in the Web application, shutdown only closed the Web thread (the default listening port 8080), closed the thread (default listening 8005), and for the executorservice created through the thread pool (including executors), Can only be cleared manually. The advantage of using a Tomcat container is the ability to wrap the lifecycle of the application, such as solving this problem by implementing the Contextdestroyed method inside the Servletcontextlistener to manually delete it.
Multi-threaded (thread pool) shutdown is a few stages, running->shutdown->stopt->idying->terminated, the IsShutDown () provided by the thread pool object corresponds to the SHUTDOWN phase , isterminated () corresponds to the terminated stage, where the first call to shutdown, the return is true, the latter only returns true if the task in all the thread pools has ended (interrupt processing and exit).
This means that all multithreaded runnable/callable implementations, if it is a while (true) pattern, should be captured for interrupt exceptions and exited.
while (true) {
try{
... ...
catch (Interruptedexception e) {
Logger.warn ("Responsequeuehandler received interrupt request, exit program");
return;
}catch (Throwable e) {
... ...
}
}
Most of the time we deal with exceptions, we capture and record them, avoid any processing impact, but exit from processing for interrupt exceptions, and only close will initiate an interrupt request to a thread (if there are other implementation scenarios that also trigger an interrupt), so as long as you break, you exit.
The mechanism of interrupt handling, based on our discussion above, is as follows:
public static void Shutdownthread (Executorservice service, String serviceName) {
Service.shutdown ();
try {
if (!service.isterminated ()) {
Logger.debug ("Direct shutdown failed {}", serviceName);
Service.awaittermination (3, timeunit.seconds);
if (service.isterminated ()) {
Logger.debug ("successfully closed {}", serviceName);
} else {
Logger.debug ("{} shutdown failed, direct shutdownnow! ", ServiceName);
if (Service.shutdownnow (). Size () > 0) {
Logger.debug ("final {} did not close successfully", serviceName);
} else {
Logger.debug ("Shutdownnow finally successfully closed {}", serviceName);
}
}
} else {
Logger.debug ("Direct successful Close {}", serviceName);
}
} catch (Interruptedexception e) {
Logger.warn ("received interrupt request, {} stop operation", ServiceName);
}
}
My application in the implementation of the time, Fixedschedulethread, or newcachablethread are alone to make, now think back, actually should let them all come from the same executorservice, so, In contextdestroyed in fact just close a executorservice can, now is to close a bunch.
For the thread pool to close (the code above is a common way to close threads), additional processing is required:
For (future<string> future:this.runTaskMap.values ()) {
Future.cancel (TRUE);
}
The thread pool will have more than the future is canceled, this process is actually the process of interrupting the thread, one after the thread break, then the Executorservice shutdown () operation.
Kill-9 tomcat_pid will be violent shut down should be used, kill Tomcat_pid will gracefully shut down the thread, just like the shutdown effect of calling the thread pool.
Finally, there can be a much simpler and more brutal way of calling exit (0) in contextdestroyed. When you start using it, worry about killing the entire JVM of the machine. But if you understand the principle of the JVM, in fact, every running Java program has its own JVM, and does not interfere with each other. In addition, if you want to do something before exit (0), you can add hooks for the JVM to handle such things as closing the thread:
@Override
public void contextinitialized (Servletcontextevent sce) {
Logger.info ("New version 2016-12-12 22:19");
... ...
Runtime.getruntime (). Addshutdownhook (New Thread (new Runnable () {
@Override
public void Run () {
... ...
threadmanager.getinstance (). shutdown ();
}
}));
}
Ignore the first row of log, the intention is to hit the version number, proving that the running JAR package is the latest version.
The way we mentioned above to close the thread can be put here.
Shutdown completely shut Tomcat, and multithreading off