Norbert94
Norbert94

Reputation: 173

Java ExecutorService sequentially -Spring MVC

I want to implement the ExecutorService in my Spring-MVC application.

I need a global ExecutorService which take tasks put them in a queue and then executes them sequentially. So I want to pass the tasks from different locations in the application. Therefore I am using the Executors.newSingleThreadExecutor(); so I have only 1 thread executing these tasks.

However, I am not sure how to integrate it in a Spring application:

public enum TaskQueue {

    INSTANCE;

    ExecutorService executorService;

    private TaskQueue() {
        executorService = Executors.newSingleThreadExecutor();
    }

    public void addTaskToQueue (Runnable task){
        executorService.submit(task);
        executorService.shutdown();
    }
}

So I am thinking of creating a Singleton and then just passing the Task (Runnable object) to the method:

TaskQueue.INSTANCE.addTaskToQueue(new Runnable() {
 @Override
  public void run() {
      System.out.println("Executing Task1 inside : " + Thread.currentThread().getName());
        }
    });

However, I have several questions:

I am not sure how to integrate it in a Spring MVC application where I have controllers, services and so on.

The application receives some notifications from a web-service. These notifications will be processed on different locations in the code. I want to execute them sequentially. So I need to identify all tasks I want to run asynchronously and then pass them to the method above (`addTaskToQueue) wrapped in a Runnabel object, so they can be executed asynchronously. Is this the correct approach?

So I always pass a Runnable objects to this method to execute it. This method executes it and shuts the executorservice down. So each time I pass a task to this service - it creates a new service and then closes it. But I dont want to have that - I want the executorservice to stay alive and execute the tasks that are comming and not shutdown after each task. How do I achieve this?

Or am I totally wrong in implementing it this way?

EDIT:

Using the TaskExecutor provided by Spring - I would implement it like this:

@Autowired
private TaskExecutor taskExecutor;

Then calling it from different location in my code:

taskExecutor.execute(new Runnable() {
        @Override
        public void run() {
            //TODO add long running task
        }
    });

Probably I need to make sure somewhere in the configuration that it needs to be executed sequentially - so it should create only 1 thread. Is it safe to call it from different locations? It wont always create a new service with a new queue?

Upvotes: 0

Views: 2483

Answers (2)

SeverityOne
SeverityOne

Reputation: 2721

The Singleton design pattern is not a very good fit for this. Since you're using Spring, it makes much more sense to make a component with @PostConstruct and @PreDestroy methods. Here and here are articles that explain this.

In your case, I'd do something like the following:

@Component
public class TaskQueue {

    private ExecutorService executorService;

    @PostConstruct
    public void init() {
        executorService = Executors.newSingleThreadExecutor();
    }

    @PreDestroy
    public void cleanup() {
        executorService.shutdown();
    }

    public void addTaskToQueue (Runnable task){
        executorService.submit(task);
    }
}

And then you can autowire this component.

Edit: @Ivan's answer is to be preferred.

Upvotes: 0

Ivan
Ivan

Reputation: 8758

Spring already has a bean for this: org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor. It implements DisposableBean interface and shutdown() method is called when Spring context is destroyed.

  <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="${threadPoolSize}"/>
    <property name="maxPoolSize" value="${threadPoolSize}"/>
    <property name="WaitForTasksToCompleteOnShutdown" value="false"/>
  </bean>

Upvotes: 3

Related Questions