0

The application I am working on receives notifications from external systems, which I want to process sequentially, since I am experiencing some deadlocks.

I am using the TaskExecutor from Spring which is the equivalent of the JDK 1.5's Executor.

I've implemented it in the following way:

I've a java interface containing 1 method:

    public interface AsynchronousService {
    void executeAsynchronously(Runnable task);
}

and the corresponding implementation:

    public class AsynchronousServiceImpl implements AsynchronousService {

    private TaskExecutor taskExecutor;

    @Override
    public void executeAsynchronously(Runnable task) {
        taskExecutor.execute(task);
    }

    @Required
    public void setTaskExecutor(TaskExecutor taskExecutor) {
        this.taskExecutor = taskExecutor;
    }
}

Here is the configuration of the TaskExecutor. I am not sure about this configuration. Since, I want the notifications to execute sequentially, I set 1 for both, corePoolSize and maxPoolSize. This means that only 1 thread will be created in the threadpool and retrieves the notifications sequentially from the queue. I also set "false" for "WaitForTasksToCompleteOnShutdown" in order not to shutdown after each task is executed, but rather when the spring context is destroyed. Am I generally correct with my assumptions?

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

Here I execute then the code:

 asynchronousService.executeAsynchronously(new Runnable() {
     @Override
     public void run() {
         someMethod.processNotification(notification)
      }
   });

What do you think of my implementation? Did I miss something? I am not sure if/where I need to implement some error-handling?

EDIT: Is there any possibilty to tweak the implementation of the task-executor in spring to use a custom queue? Or how difficult is it to prioritize the tasks in the queue? I looked at some implementations but most of them implement the executor-service from sratch without using Spring.

Norbert94
  • 173
  • 2
  • 17

1 Answers1

2

The application I am working on receives notifications from external systems, which I want to process sequentially, since I am experiencing some deadlocks.

If you process sequentially, you don't need thread pool anyway.

Since, I want the notifications to execute sequentially, I set 1 for both, corePoolSize and maxPoolSize

This will create a fixed pool size of 1. There's only one thread so it will execute sequentially

I also set "false" for "WaitForTasksToCompleteOnShutdown" in order not to shutdown after each task is executed, but rather when the spring context is destroyed

This is wrong. This flag tells the pool to wait for task completion on shutdown (Eg. If you call pool.shutdownNow(), the pool will wait for any executing threads)

And to summarize: Don't use thread pool if you want to execute one by one serially without concurrent

Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51
  • Thanks for your answer. What am I then supposed to use, when I want to put the notification in a queue and execute them asynchronously? After I did some research, it was suggested that one should use the Executor-Framework from Java, since it abstracts the complex implementation from you - And since I am in a Spring-Project I thought of using the spring equivalent, which is the task executor, which makes it even more simple – Norbert94 May 22 '18 at 09:57
  • Does your process logic access shared resource? Like modify state of an object, modify static resource, etc... Why do you know you have a deadlock? Which part of your program cause deadlock? – Mạnh Quyết Nguyễn May 22 '18 at 09:58
  • Thx for the fast reply. Mostly i retrieve information from this notificationObject and save them in the database. The problem is that, if the application receives multiple notifcations and processes them ,which sometimes lead to deadlocks. it is very difficult to reproduce these deadlocks – Norbert94 May 22 '18 at 10:04
  • Therefore I want to put the notifiaciton in a queue and apply the logic in an asynchrony way. I was inspired from this aswer: https://stackoverflow.com/questions/39912669/executorservice-that-executes-tasks-sequentially-but-takes-threads-from-a-pool?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa – Norbert94 May 22 '18 at 10:06
  • Is the queue is from another side or you're creating your queue by yourself? – Mạnh Quyết Nguyễn May 22 '18 at 10:17
  • I don't create queue at all. I use the default queue (I believe it is the unbounded LinkedBlockingQueue) created by the Executor-Service framework. Of course I can change that in the spring-configuration – Norbert94 May 22 '18 at 10:22
  • That's clear now. Just increase your pool size, no need to set it fix to 1. Then push the task to the pool by `poo.execute`. And you're done. The pool will queue the task for you – Mạnh Quyết Nguyễn May 22 '18 at 10:26
  • But if I increase the pool-size, then the task would not run sequentially? And with "poo.execute" you mean like I did in my implementation (taskExecutor.execute(task);) – Norbert94 May 22 '18 at 10:31
  • Why do you want it to execute in sequentially? Post your revelant code here, I will tell you where's the prob – Mạnh Quyết Nguyễn May 22 '18 at 10:33
  • This is a huge application, so it is difficult to post here all the tasks which are peformed after receiving the notification (mostly writing into a database ). But I get it, I should find the source of the code where the deadlock happens and fix it. If I halve multpiple threads then the notifications are running in parallel, and it does not automatically make it safe to concurrently access shared state across threads - also the order of the execution can be different. That's why I want to execute them sequentially, because then it would be too complex. Do you agree? – Norbert94 May 22 '18 at 12:31
  • As long as you do not modify shared resource, nothing prevent you from using multiple thread concurrently – Mạnh Quyết Nguyễn May 22 '18 at 12:33
  • The logic that is applied asynchronously is like setting some variables, writing something in the database and so on. So I need to make sure that this code like setting a boolean variable to true, is executed in a synchronized way (putting them in synchronize block). Can you give an example what you mean with "shared resource". Sry, I am still trying to learn concurrent programming – Norbert94 May 23 '18 at 09:20
  • If you can share code with me I might able to help you. Shared resource is something like: Modify the same instance (like both write to a single list).. – Mạnh Quyết Nguyễn May 23 '18 at 09:22
  • It is difficult to post the whole code, since it is huge. But thx very much for your help . I understand what you mean. – Norbert94 May 23 '18 at 12:32
  • I think you should creat another question. Tag me the link and I will help you then – Mạnh Quyết Nguyễn May 28 '18 at 13:17
  • https://stackoverflow.com/questions/50569540/spring-taskexecutor-implementation-queue-priorization – Norbert94 May 28 '18 at 15:28