In this tutorial we will start a thread on the application startup using spring bean.So we will start the thread using @PostConstruct
annotation on the method. So this makes sure that the annotated method is called before the Spring bean is put into service. And we will be using executor service to start a thread. Here is the method
@PostConstruct public void init() { BasicThreadFactory factory = new BasicThreadFactory.Builder() .namingPattern("myspringbean-thread-%d").build(); executorService = Executors.newSingleThreadExecutor(factory); executorService.execute(new Runnable() { @Override public void run() { try { // do something System.out.println("thread started"); } catch (Exception e) { logger.error("error: ", e); } } }); executorService.shutdown(); }
Let me explain what I am doing in the above method. I am using BasicThreadFactory so that thread has a name and would be easy while reading logs to find out which thread is doing which task. You can start the thread without it, like below.
executorService = Executors.newSingleThreadExecutor(factory);
So in the thread I am just printing out something. This can be replaced by your custom code.
And the executorService.shutdown() makes sure that thread is executed. And this method does not wait for the thread to finish.
And finally let us look to have a graceful shutdown in case spring bean is destroyed while the thread is executing. This is done using the @PreDestroy annotation.Here is the method.
@PreDestroy public void beandestroy() { if(executorService != null){ executorService.shutdownNow(); } }
So this method calls executorService.shutdownNow(); which tries to stop the threads immediately. You can see in the javadocs of this method that it only makes the best effort to shutdown.
Now let us have the whole picture and here goes the bean. You can see how simple it is.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.apache.logging.log4j.Logger; import org.springframework.stereotype.Component; @Component public class MySpringBean { private static final Logger logger = org.apache.logging.log4j.LogManager .getLogger(MySpringBean.class); private ExecutorService executorService; @PostConstruct public void init() { BasicThreadFactory factory = new BasicThreadFactory.Builder() .namingPattern("myspringbean-thread-%d").build(); executorService = Executors.newSingleThreadExecutor(factory); executorService.execute(new Runnable() { @Override public void run() { try { // do something System.out.println("thread started"); } catch (Exception e) { logger.error("error: ", e); } } }); executorService.shutdown(); } @PreDestroy public void beandestroy() { if (executorService != null) { executorService.shutdownNow(); } } }
If you are doing some IO operations in your threads please have a look at the post.
Nice article. It happens to be exactly what I need right now. Extra credit for naming the thread and including clean shutdown.