As mentioned in SPR-10556, overlapping executions won't occur.

But in my project, I have a scheduled task which has to run every hour (with cron expression 0 20 * * * ?) .In most case, it took 20 to 30 minutes. But sometimes, it took 2 to 3 hours due to force majeure. Though there is a way to solve it by submitting the task to a separate thread pool, it would be better if spring-context support overlapping executions.

For now, I solve it by the following codes:

  1. BaseOnLSETCronTrigger.java which copy from org.springframework.scheduling.support.CronTrigger but changed in
    /**
     * Determine the next execution time according to the given trigger context.
     * <p>Next execution times are calculated based on the
     * {@linkplain TriggerContext#lastScheduledExecutionTime completion time} of the
     * previous execution; therefore, overlapping executions will occur on purpose.
     */
    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date date = triggerContext.lastScheduledExecutionTime();
        if (date == null) {
            date = new Date();
        }
        return this.sequenceGenerator.next(date);
    }
  1. ReschedulingImmediatelyRunnable.java copy from org.springframework.scheduling.concurrent.ReschedulingRunnable and changed in
        /**
     * we firstly call schedule() and then call super.run() to keep
     * tasks which take lots of time from delaying the schedule
     */
    @Override
    public void run() {
        Date actualExecutionTime = new Date();

        this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, null);

        if (!obtainCurrentFuture().isCancelled()) {
            schedule();//schedule first
        }

        super.run();//then run
        Date completionTime = new Date();
        synchronized (this.triggerContextMonitor) {
            Assert.state(this.scheduledExecutionTime != null, "No scheduled execution");
            this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);

        }
    }
  1. To apply ReschedulingImmediatelyRunnable.java to spring-context, I copy ReshdeulingImmediatelyTaskScheduler.java from org.springframework.scheduling.concurrent.ConcurrentTaskScheduler and changed in
    @Override
    @Nullable
    public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
        try {
            ErrorHandler errorHandler =
                    (this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
            return new ReschedulingImmediatelyRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
        } catch (RejectedExecutionException ex) {
            throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
        }
    }
  1. And finally
@EnableScheduling
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {

    private static final Logger log = LoggerFactory.getLogger(ScheduleConfig.class);

    @Autowired
    private Scheduler scheduler;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

        taskRegistrar.setScheduler(new ReshdeulingImmediatelyTaskScheduler(taskExecutor()));

        /**
         * this task would took much time than expected, and it has to run every hour
         */
        taskRegistrar.addTriggerTask(() ->
                scheduler.syncPlayStatistics()
        , new BaseOnLSETCronTrigger("0 20 * * * ? "));
    }

    @Bean(destroyMethod = "shutdown")
    public ScheduledExecutorService taskExecutor() {
        ScheduledThreadPoolExecutor executorService = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(4);
        log.info("executorService:{}", executorService);
        return executorService;
    }
}

Comment From: jhoeller

This might be a good fit with SimpleAsyncTaskScheduler (#30956) which dispatches each cron-triggered task onto a separate thread, primarily targeting a Virtual Threads setup. Beyond that, we do not intend to support overlapping executions specifically.