0

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?

7
  • 2
    Why do you shut down the ExecutorService immediately after adding a task to it? Commented May 1, 2018 at 18:09
  • @SeverityOne But when do I have to shut it down? I want to to pass tasks from multiple places in the spring application and I dont know where to put the shutdown. Commented May 1, 2018 at 18:10
  • When you no longer need it. I'd better write an answer for this. Commented May 1, 2018 at 18:11
  • My biggest problem is integrating the whole concept in a Spring MVC application. I have a web-service method which receives all the notifications and then other services are called to perform some tasks - Maybe I need it to put at the end of the web-service method? Commented May 1, 2018 at 18:14
  • @Norbert94 you set maxNumber of threads when configuring taskExecutor bean in XML or in Java config. By default Spring beans are singletons so only one instance of taskExecutor will be created per application context. Commented May 1, 2018 at 18:35

2 Answers 2

3

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>
Sign up to request clarification or add additional context in comments.

1 Comment

Thx for the answer - I edited my question and provided a code sample for this approach - I would appreciate it if you could check it.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.