Class SimpleAsyncTaskScheduler

All Implemented Interfaces:
Serializable, AutoCloseable, Executor, EventListener, Aware, ApplicationContextAware, ApplicationListener<ContextClosedEvent>, Lifecycle, Phased, SmartLifecycle, AsyncListenableTaskExecutor, AsyncTaskExecutor, TaskExecutor, TaskScheduler

A simple implementation of Spring's TaskScheduler interface, using a single scheduler thread and executing every scheduled task in an individual separate thread. This is an attractive choice with virtual threads on JDK 21, expecting common usage with setVirtualThreads(true).

NOTE: Scheduling with a fixed delay enforces execution on the single scheduler thread, in order to provide traditional fixed-delay semantics! Prefer the use of fixed rates or cron triggers instead which are a better fit with this thread-per-task scheduler variant.

Supports a graceful shutdown through SimpleAsyncTaskExecutor.setTaskTerminationTimeout(long), at the expense of task tracking overhead per execution thread at runtime. Supports limiting concurrent threads through SimpleAsyncTaskExecutor.setConcurrencyLimit(int). By default, the number of concurrent task executions is unlimited. This allows for dynamic concurrency of scheduled task executions, in contrast to ThreadPoolTaskScheduler which requires a fixed pool size.

NOTE: This implementation does not reuse threads! Consider a thread-pooling TaskScheduler implementation instead, in particular for scheduling a large number of short-lived tasks. Alternatively, on JDK 21, consider setting SimpleAsyncTaskExecutor.setVirtualThreads(boolean) to true.

Extends SimpleAsyncTaskExecutor and can serve as a fully capable replacement for it, e.g. as a single shared instance serving as a TaskExecutor as well as a TaskScheduler. This is generally not the case with other executor/scheduler implementations which tend to have specific constraints for the scheduler thread pool, requiring a separate thread pool for general executor purposes in practice.

NOTE: This scheduler variant does not track the actual completion of tasks but rather just the hand-off to an execution thread. As a consequence, a ScheduledFuture handle (e.g. from schedule(Runnable, Instant)) represents that hand-off rather than the actual completion of the provided task (or series of repeated tasks).

As an alternative to the built-in thread-per-task capability, this scheduler can also be configured with a separate target executor for scheduled task execution through setTargetTaskExecutor(java.util.concurrent.Executor): e.g. pointing to a shared ThreadPoolTaskExecutor bean. This is still rather different from a ThreadPoolTaskScheduler setup since it always uses a single scheduler thread while dynamically dispatching to the target thread pool which may have a dynamic core/max pool size range, participating in a shared concurrency limit.

Since:
6.1
Author:
Juergen Hoeller
See Also: