Giovanni Botta Giovanni Botta - 2 days ago 4
Java Question

How to properly shutdown executor services with Spring?

I have a command line application that uses a Spring-managed bean that's composed of a java

ExecutorService
created with:

ExecutorService service = Executors.newFixedThreadPool(4);


Now, I want my service to shutdown when my application shuts down, so I made my bean implement the
DisposableBean
interface and have a destroy method such as:

public void destroy(){
service.shutdown();
}


Then I might be tempted to do something like register a shutdown hook on the Spring context. However I found out (the hard way, i.e., in a pre-production release) that this doesn't work: the shutdown hook doesn't get called before the
ExecutorService.shutdown()
method is called, causing a classic catch 22 problem (it does get called on interruption, i.e., if I hit Ctrl-C while the application is running). This escaped my unit tests because for some reason it seems to work fine from within JUnit, which is still puzzling me: what does JUnit do differently?

The solution I found so far is to explicitly call
ApplicationContext.close()
right before I exit my main function. I was wondering if there was a better solution to this and what are the best practices for having flexible thread pools managed by Spring. Also what if my bean is not directly managed by Spring but is created by a bean managed by Spring? Should I just cascade the calls to
destroy()
? Wouldn't this be very error prone?

I appreciate any comments, suggestions, further reading, RTFMs, magic recipes.

Thanks!

Answer

Are you aware that this:

ExecutorService service = Executors.newFixedThreadPool(4);

can be replaced with this:

<bean id="service" class="java.util.concurrent.Executors" 
      factory-method="newFixedThreadPool" destroy-method="shutdown">
    <constructor-arg value="4"/>
</bean>

The spring context then manages, more directly, the shutdown of your executor service--and it can be more easily reused.

Comments