Using @Scheduling to run method at @Scheduled(fixedRate = 10000) and set up @Scheduling threading by implementing SchedulingConfigurer
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10);
}
if I used Thread.sleep or Lock , no other thread is created by Executor unless Thread.sleep wake up or lock is cleared.
Can someone explain internal working if i have 10 pool size they 10 threads should be created at rate of 10000 millisec.
In the case that you use threadpool: By default you going to have 10 threads in your pool(already initialized). The first time that @scheduled is executed, this function is going to execute in a thread from your pool (now remaining 9 threads), if the function yet finished and @scheduled is executed again, your function going to executed in other thread from you your pool, so now you have 8 thread remaining in your pool. (8 idle, 2 running threads)
If you aren`t use threadpool only one thread is used.
spring documentation:
If you do not provide a 'pool-size' attribute, the default thread pool will only have a single thread. There are no other configuration options for the scheduler.
https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/scheduling.html
Basically such behavior comes from ScheduledExecutorService
implementation which is used internally by spring. If you will run this code you will notice the same behavior:
public static void main(String[] args) throws Exception {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
executor.schedule(() -> {
System.out.println("Running task in thread " + Thread.currentThread().getId());
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
System.out.println("interrupted while sleeping");
}
}, 1000, TimeUnit.MILLISECONDS);
Thread.sleep(10000);
executor.shutdownNow();
}
When you submit task to scheduled thread pool it is wrapped with RunnableScheduledFuture
which is passed to delayedExecute
method. This method adds the task to the tasks queue and starts new worker if current number of workers is less than corePoolSize
. Worker tries to get a task from the queue and process it invoking run
method. There is a dedicated DelayedWorkQueue
implementation which returns tasks only if they are ready for execution. Here is how run
method of RunnableScheduledFuture
looks like:
/**
* Overrides FutureTask version so as to reset/requeue if periodic.
*/
public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) {
setNextRunTime();
reExecutePeriodic(outerTask);
}
}
As you can see it invokes actual task logic in runAndReset
, calculates the next running time and submits the same updated task to the queue again ( reExecutePeriodic
is almost the same as schedule
). There is only a single periodic task for all executions which is resubmitted again and again with updated time after the previous execution is finished. So such thread pool runs only a single instance of each task type in any given moment and scales only for different type of tasks.
If you are interesting in how spring schedules tasks take a look at ScheduledTaskRegistrar
class and particularly at scheduleFixedDelayTask
method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.