Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does pool size actually work with Spring's scheduled tasks?

I have a task scheduled as such:

<task:scheduler id="notification.scheduler" pool-size="15" />

<task:scheduled-tasks scheduler="notification.scheduler">
    <task:scheduled ref="notificationProcessor" method="sendNextQueueEvent" fixed-rate="500" />
    <task:scheduled ref="notificationProcessor" method="deleteNextCompletedEvent" fixed-rate="60000" />
</task:scheduled-tasks>

I think I have a misunderstanding of how the scheduled tasks work with the pool size. Despite the pool-size being 15, it seems only one thread is being used. For example, if I have fifteen events in the queue, I would think there would be fifteen threads checking every minute to remove an event from the queue. Obviously, this is wrong.

How can I make it so that there's fifteen threads calling this method for the time interval using Spring's scheduler abstraction?

Edit: What I want to accomplish is this: Every half second, I want to check to see if there are queued events to send. When this is done, I want to send a maximum of 15 (if 15 exist). How would I accomplish this using the spring abstractions for the java thread stuff?

like image 389
AHungerArtist Avatar asked Apr 20 '12 18:04

AHungerArtist


People also ask

What is pool size in TaskScheduler?

spring.task.scheduling.pool.size=20. The same task will be executed in serialized when the trigger period is shorter than the execution duration. And Spring Boot will execute different tasks in parallel with a maximum of 20 threads.

How does @scheduled work in Spring?

We can turn any method in a Spring bean for scheduling by adding the @Scheduled annotation to it. The @Scheduled is a method-level annotation applied at runtime to mark the method to be scheduled. It takes one attribute from cron , fixedDelay , or fixedRate for specifying the schedule of execution in different formats.

What is the use of TaskExecutor in Spring?

The TaskExecutor was originally created to give other Spring components an abstraction for thread pooling where needed. Components such as the ApplicationEventMulticaster , JMS's AbstractMessageListenerContainer , and Quartz integration all use the TaskExecutor abstraction to pool threads.


2 Answers

First of all <task:scheduler/> is a wrapper around ScheduledThreadPoolExecutor extending ThreadPoolExecutor. JavaDoc for the latter says:

even core threads are initially created and started only when new tasks arrive

Secondly you must understand that scheduled tasks (this is a Java feature, not Spring's) do not run concurrently, even if they take longer time than repeat interval. They simply wait. So you don't have 15 events waiting in the queue, you have 15 executions that are late and wait for that single thread. No need to create another one because next execution has to wait for the previous one to finish. Again, this is how Java scheduling framework works.

Of course if you have several different tasks scheduled, more threads will be created.

like image 197
Tomasz Nurkiewicz Avatar answered Sep 24 '22 21:09

Tomasz Nurkiewicz


Spring's task:scheduler is by default a bean properties wrapper for java.util.concurrent.ThreadPoolExecutor:

corePoolSize - the number of threads to keep in the pool, even if they are idle.

This does not guarantee that the pools-size property is equivalent to having that number of active threads. On the other hand, you should note that at any given point in time there can be only a maximum number of threads equal to processing cores on the machine that you're using; i.e. all other threads will be waiting to switch to RUNNING mode and continue execution.

Also, in Spring's documentation, it mentions that if this is not what you need, you can also take advantage of ConcurrentTaskExecutor.

like image 23
nobeh Avatar answered Sep 23 '22 21:09

nobeh