0

I'm using the ExecutorService on a @EnableScheduling class to submit multiple executions of the same method.

Basically, my configuration is:

@Component
@EnableScheduling
public class JobQueue {
  
  @Autowired
  private JobQueueService jobQueueService;

  private Integer threadPoolSize = 5;

  private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);

  @Scheduled(fixedDelay = 20_000)
  private void run() {
    for (int i = 0; i <= threadPoolSize; i++) {
      Runnable runnableTask = () -> {
        jobQueueService.processPendingJobs();
      };

      executorService.submit(runnableTask);

      // Also, tried with executorService.execute(runnableTask);
    }
  }
}

But, the JobQueueService.processPendingJobs() is running only in single-thread executions, even when it is called multiple times with the for on my scheduled class.

Has Spring a different Autowired implementation for multi-threaded purposes?

I also tried instantiating a new service on for-of loop for each execution:

JobQueueService jobQueueService = new JobQueueService();

...[Runnable code chunk]

And at this time, it calls multiple thread executions, but loses Spring Application Context (Beans and other properties).

Do I have to provide a specific Bean implementation for my JobService to run it in multi-threaded contexts and still use it as an Autowired component?

The processPendingJobs() is annotated with synchronized keyword, is that wrong? If yes, why?

@Service
public class JobQueueService {

  public synchronized void processPendingJobs() {
    // Run logic
  }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197

1 Answers1

0

You can make the call to processPendingJobs() run in a new thread by annotating the method with Spring's @Async annotation. This annotation only works on public methods and they should always be called from another class. To enable asynchronous calling you also need to annotate a @Configuration annotated class with the @EnableAsync annotation.

Maurice
  • 6,698
  • 9
  • 47
  • 104
  • Actually, I need to keep the `processPendingJobs()` syncronized due to other executions depending on it, this method is annotated with the `synchronized` keyword, is that wrong? – viniciusmfelix Mar 15 '22 at 14:08
  • 1
    Do you know [what synchronized does](https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)? **When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.** – Christopher Schneider Mar 15 '22 at 14:20
  • 1
    @viniciusmfelix when you make a method `synchronized` only one thread will be able to call the method at a given time. If another thread calls the same method while the first thread isn't yet finished running the method then that thread will have to wait until the first one is finished. So thats why you see only one thread executing it at a time. – Maurice Mar 15 '22 at 14:21
  • also, the keyword `synchronized` is part of the `java` language. It has nothing to do with Spring. – Maurice Mar 15 '22 at 14:22