ExecutorService doesn't shut down from contextDestroyed() when stopping Tomcat

executorservice, java, multithreading, tomcat

Solution

The problem is that you have two different `RoomsManager` instances (and hence, two different executors): first is created by Tomcat, and second is created by you.

When you annotate `RoomsManager` with `@WebListener`, Tomcat automatically creates an instance of that class and subscribes it to receive servlet context create/destroy events. That instance is the one that actually stops its executor and prints `ServletContextListener destroyed`.

The second instance is created by you in the `getRoomsManager` method (by the way, that method doesn't look thread-safe). That instance is not registered with Tomcat and doesn't receive servlet context "destroy" event, so it doesn't even try to shutdown its executor.

Problem

I have a `ExecutorService executor = Executors.newSingleThreadExecutor();` that i want to stop when the server is shutting down. I have a class that `implements ServletContextListener` and it's annotated with `@WebListener`. I have the two methods in that class: ``` @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("ServletContextListener started"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { executor.shutdown(); executor.shutdownNow(); System.out.println("ServletContextListener destroyed"); } ``` And I see that it prints what's in both of them when it's supposed to, but when I press the stop button once in intelij, I get: SEVERE: The web application [] 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. Right after it printed `ServletContextListener destroyed`. I need to press the stop button again to fully stop it. Why it doesn't shutdown the ExecutorService even though it reached the `executor.shutdown();`? What am I doing wrong? PS: this is the only ExecutorService I have and no other threads are made by me. EDIT2: The executor service is a field in a singleton class, it's initialized with the class: ``` private ExecutorService executor = Executors.newSingleThreadExecutor(); ``` This is how the class is initialized (lazy initialization): ``` public static RoomsManager getRoomsManager(ServletContext servletContext) { if (servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME) == null) { servletContext.setAttribute(MANAGER_GAMES_ATTRIBUTE_NAME, new RoomsManager()); } return (RoomsManager)servletContext.getAttribute(MANAGER_GAMES_ATTRIBUTE_NAME); } ``` And is annotated like this: ``` @WebListener public class RoomsManager implements ServletContextListener { ``` The stop button is the red square near the play and debug buttons in intelij IDEA.

Original source

Related problems