kuhaku kuhaku - 1 month ago 11
Java Question

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

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.

EDIT: I changed it to:

class YourThreadFactory implements ThreadFactory {
public Thread newThread(Runnable r) {
return new Thread(r, "Your name");
}
}
private ExecutorService executor = Executors.newSingleThreadExecutor(new YourThreadFactory());


And now it shuts down properly, how does that even make sense?

Answer

Doing this worked:

class YourThreadFactory implements ThreadFactory {
    public Thread newThread(Runnable r) {
        return new Thread(r, "Your name");
    }
}
private ExecutorService executor = Executors.newSingleThreadExecutor(new YourThreadFactory());

Because apparently, the threads of tomcat are daemons, and therefore, when they create a new thread with return new Thread(r, "Your name"); it also becomes a daemon.

But in the DefaultThreadFactory that an executor service use, I saw that it makes sure daemonity of new threads is off.

That doesn't explain why executor.shutdown(); didn't work though, but now at least it properly shuts down.