javaspringscheduled-tasksquartz-schedulerquartz

Spring TaskScheduler does not schedule task immediatelly


I want to execute the same task couple of times but it seems that every next invocation of my code does not execute the task immediately, for example it executes after one minute.

Since user has to schedule tasks manually I use ScheduledTaskRegistrar.TaskScheduler.

taskRegistrar.getScheduler().schedule(myTask, new Date());

What could be the reason? User clicked schedule button twice on my fronted application and backend invoked the above schedule method twice as expected. First execution of my task was immediate, second run after two minutes.

UPDATE: taskregistrar config, maybe I didn't configure it at all. my tasks are added as cron tasks on application deployment. But they also must be runnable manually if user wants to trigger it. Below is more or less the whole logic:

@Configuration
@EnableAsync
@EnableScheduling
@Component
@Slf4j
@Generated
@Getter
public class ScheduleTaskService implements SchedulingConfigurer {
    @Autowired
    private List< MyTask> taskList;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        this.taskRegistrar = taskRegistrar;
        taskList.stream().filter(MyTask::isOn).forEach(this::addTaskToScheduler);
    }

    public void addTaskToScheduler(GwoTask task) {
        taskRegistrar.addCronTask(task, task.getCronExpression());
    }
    public void scheduleImmediateInvocation(MyTask myTask) {
        taskRegistrar.getScheduler().schedule(myTask, new Date());
    }
}

Solution

  • By referring to the source code of ScheduledTaskRegistrar,

        protected void scheduleTasks() {
            if (this.taskScheduler == null) {
                this.localExecutor = Executors.newSingleThreadScheduledExecutor();
                this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
            }
            ...
    

    If we do not set taskScheduler, Executors.newSingleThreadScheduledExecutor() is used by default. Hence new task will be blocked by processing task.

    For your use case in scheduleImmediateInvocation, I recommend to use another thread pool(Probably from Executors) instead as:

    If you just want to make ScheduledTaskRegistrar execute more concurrently, configure it as:

        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            // set the desired core pool size
            taskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
            this.taskRegistrar = taskRegistrar;
            // ...
        }