Spring provides the TaskExecutor interface as an abstraction for dealing with Executor. The implementation classes of TaskExecutor are as follows:
- SimpleAsyncTaskExecutor: This starts a new thread and executes it asynchronously. It does not reuse the thread.
- SyncTaskExecutor: This executes each task synchronously in the calling thread. It does not reuse the thread.
- ConcurrentTaskExecutor: This exposes bean properties for configuring java.util.concurrent.Executor.
- SimpleThreadPoolTaskExecutor: This is a subclass of SimpleThreadPool of Quartz, which listens to Spring's life cycle callbacks.
- ThreadPoolTaskExecutor: This exposes bean properties for configuring java.util.concurrent.ThreadPoolExecutor and wraps it in TaskExecutor.
- TimerTaskExecutor: This implements a single TimerTask class as its backing implementation. It executes methods as synchronous in a separate thread.
- WorkManagerTaskExecutor: This uses the CommonJ WorkManager interface as its backing implementation.
Let's see a simple example of executing a task with SimpleAsyncTaskExecutor in the Spring application. It creates a new thread for each task submission and runs as asynchronous.
Here is the configuration file:
@Configuration
public class AppConfig {
@Bean
AsyncTask myBean() {
return new AsyncTask();
}
@Bean
AsyncTaskExecutor taskExecutor() {
SimpleAsyncTaskExecutor t = new SimpleAsyncTaskExecutor();
return t;
}
}
Here is the bean class where we have assigned 5 tasks to TaskExecutor:
public class AsyncTask {
@Autowired
private AsyncTaskExecutor executor;
public void runTasks() throws Exception {
for (int i = 1; i <= 5; i++) {
Runnable task = new Task(" " + i);
executor.execute(task);
}
}
}
The following is the code for executing the task from the main method:
public class TaskExecutorExample {
public static void main(String[] args) throws Exception {
ApplicationContext context = new
AnnotationConfigApplicationContext(AppConfig.class);
AsyncTask bean = context.getBean(AsyncTask.class);
bean.runTasks();
}
}
When we compile and run the preceding class, we will get the following output. Here, we can see five threads are created and they execute the task asynchronously:
SimpleAsyncTaskExecutor-1, Execute Task = 1
SimpleAsyncTaskExecutor-4, Execute Task = 4
SimpleAsyncTaskExecutor-3, Execute Task = 3
SimpleAsyncTaskExecutor-2, Execute Task = 2
SimpleAsyncTaskExecutor-5, Execute Task = 5
SimpleAsyncTaskExecutor-2, End
SimpleAsyncTaskExecutor-1, End
SimpleAsyncTaskExecutor-4, End
SimpleAsyncTaskExecutor-3, End
SimpleAsyncTaskExecutor-5, End