I have a web app which runs an interface for controlling an irrigation system. The system starts up to 10 or so threads, using a ScheduledThreadPoolExecutor.
I have found that when I close down the server, many of these threads continue to run. From the Tomcat catalina.out log:
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [GH2] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak.
The classes that start these threads are dotted around my app. In order to try to have some control over stopping them, I have a single ScheduledThreadPoolExecutor created by a ServletContextListener and passed into each of the classes that might start a task.
I have tried setting properties in the ScheduledThreadPoolExecutor that I assumed would close down all threads when contextDestroyed() is called in the listener:
public void contextInitialized(ServletContextEvent event) {
executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10);
executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
executor.setRemoveOnCancelPolicy(true);
event.getServletContext().setAttribute("executor", executor);
Here is a typical bit of code that schedules a thread:
public WeatherScheduler(ScheduledThreadPoolExecutor executor) {
this.executor = executor;
checkEveryHour();
}
public void checkEveryHour() {
final Runnable weatherChecker = new Runnable() {
public void run() {
if (!Thread.interrupted()) {
if (Date_TimeUtils.isBetween7amAnd8pm()) {
weather = new Weather();
weather.getNewForecast();
IrrigationLogger.getInstance().logEvent("weather forecast: " + weather.toString());
} else
LOGGER.log(Level.INFO, "weatherChecker not called as isBetween7amAnd8pm() == false ");
}
}
};
// delay of a minute to allow for getting internet connection, repeat every hour
executor.scheduleAtFixedRate(weatherChecker, 1, 60, TimeUnit.MINUTES);
}
When the server is closed down, the contextDestroyed() method is called in the listener, and I have
executor.shutdownNow();
included in that method.
But still I get the message in the log file that threads have been started that can't be stopped.
What am I missing?
Thanks.