A backend webapp is deployed on a Tomcat 6 servlet container. In the webapp, several monitoring threads are started. The problem is with shutdown.
Currently my thread is implemented as below. When the servlet is instructed to shutdown (shutdown.sh) it does complete a clean shutdown and does not hang because of this thread -- Why?
class Updater extends Thread {
volatile boolean interrupted = false;
@Override
public void run() {
Integer lastUpdateLogId = CommonBeanFactory.getXXX()
.getLastUpdateLogRecordKey(MLConstants.SMART_DB_NAME);
List<UpdateLog> updateLogRecords;
while (!interrupted) {
boolean isConfigurationUpdateRequested = false;
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
setInterrupted(true);
}
updateLogRecords = CommonBeanFactory.getXXX()
.getLastFactsUpdateLogRecords(MLConstants.XXXX, lastUpdateLogId);
for(UpdateLog updateLog : updateLogRecords) {
if (updateLog.getTable_name().equals(MLConstants.CONFIG_RELOAD)) {
isConfigurationUpdateRequested = true;
}
lastUpdateLogId = updateLog.getObjectKey();
}
if (isConfigurationUpdateRequested) {
Configuration.getInstance().loadConfiguration();
}
}
}
public boolean getInterrupted() {
return interrupted;
}
public void setInterrupted(boolean interrupted) {
this.interrupted = interrupted;
}
}
I guess I can't reply to answers yet. Eddie's answer is not quite correct.
I found this question because I'm trying to figure out why my webapp doesn't shut down properly; I have threads that don't get killed when I run shutdown.*. In fact, it stops some threads but ultimately just sits there in some limbo state. My class is almost exactly like this one, actually.
Typing Ctrl+C in the foreground Tomcat window (on Windows) does stop everything, however using the init script that comes with Tomcat does not. Unfortunately, I haven't figured out why yet...
Edit: I figured it out. Most of my monitoring threads are started in a ServletContextListener, but when that context was "destroyed", the child threads weren't notified. I fixed it by simply keeping all child threads in a List and looping through, calling Thread.interrupt() on each within the contextDestroyed() method. It's almost the same as what Eddie said about the servlet destroy() method.
However, it's not correct that the JVM is summarily shut down when you run shutdown.{sh|bat}. It's more like that script sends a shutdown request to the Tomcat components. It's up to you to receive those shutdown messages and pass them along to your own objects.
Servlets receive a lifecycle event when instructed to shut down. You can use this event to stop your monitoring Thread. That is, when a servlet is started, its init()
method is called. When it is stopped, its destroy()
method is called.
Override the destroy()
method in your servlet and stop the thread there.
When you call shutdown.sh
the whole JVM is shut down. Because the JVM stops, all threads (no matter what their state) are forcibly stopped if still running. It's the logical equivalent of calling System.exit(0);
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