Reputation: 526
In my Java web application, I am using a ScheduledThreadPoolExecutor to periodically check the database connection status.
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(0);
Runnable task = new Runnable() {
public void run() {
//check the status of the database connection, and log the result
}
};
executor.scheduleWithFixedDelay(task, 0, 10, TimeUnit.MINUTES);
However, when I logout from the web application, and close the browser window, I see (from the logs) that it is still checking for connection status.
Is there any way to terminate this executor/thread upon closing the web application?
Upvotes: 3
Views: 642
Reputation: 338835
The thread pool of an executor service may continue running after its parent app has ended. This includes web apps.
So you should always do a graceful shutdown of the executor when exiting the app. Otherwise the backing thread(s) may continue running indefinitely, like a zombie 🧟♂️.
The easiest solution is to deploy your web app to an application server supporting Jakarta Concurrency. The specification for Jakarta Concurrency 2 is current, while Jakarta Concurrency 3 is under development now.
You merely need to annotate your class(es) defining your task(s). The server will automatically detect your need for an executor service. Accordingly, the server will automatically handle creating the executor server when your web app launches as well as shutting down the executor server and its backing thread(s) when your web app is ending. Very easy.
Products that support Jakarta Concurrency include Apache TomEE (Plume & Plus editions), Payara, Glassfish, Open Liberty, WildFly, JBoss, and more.
ServletContextListener
If you deploy to an app server that does not support Jakarta Concurrency, such as Apache Tomcat or Eclipse Jetty, then you must take manual control, and write more code.
The Servlet spec defines a hook for your web app launching and quitting.
That hook is the ServletContextListener
interface. That interface requires a pair of methods, one to be invoked by the Servlet container before the first incoming request to your web app is handled, and another method invoked after the last response has been sent out. Every Servlet container such as Tomcat is required by the spec to invoke these methods at the appropriate times.
The pair of methods are contextInitialized
and contextDestroyed
. The word “context” in Servlet-speak means “your web app”. A web container may be running any number of web apps.
In those two methods are the places for you to instantiate your executor service, and then shut it down.
You implement the interface by writing a class. You must also flag that class to the container. The easiest way to flag it is with the @WebListener
annotation.
This has been covered many times already on Stack Overflow. So search for more info and examples. Such as this Answer of mine.
Upvotes: 1
Reputation: 11
I'm not sure to have fully understood the question, but in the section for exiting from the application, you probably should do the following
executor.shutdown();
try { executor.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { }
Hoping it'll help
Upvotes: 1