Master Spring Boot 3 Task Scheduling: Interfaces, Annotations, Cron & Virtual Threads
This article explains how to use Spring Boot 3's TaskScheduler API, @Scheduled annotations, cron expressions, macro shortcuts, reactive support, virtual threads, and custom scheduling configuration, providing code examples and configuration tips for reliable backend task execution.
1. TaskScheduler Interface
Spring provides a TaskScheduler SPI with methods for scheduling tasks. The core interface is:
public interface TaskScheduler {
ScheduledFuture schedule(Runnable task, Trigger trigger);
ScheduledFuture scheduleAtFixedRate(Runnable task, Instant startTime, Duration period);
ScheduledFuture scheduleWithFixedDelay(Runnable task, Instant startTime, Duration delay);
}In a Spring Boot application you can inject it directly:
@Resource
private TaskScheduler taskScheduler;
@PostConstruct
public void initScheduler() {
this.taskScheduler.schedule(() -> {
System.out.println("执行任务");
}, new CronTrigger("*/2 * * * * *"));
}The above uses a cron expression to run every 2 seconds. You can also schedule at a fixed rate:
this.taskScheduler.scheduleAtFixedRate(() -> {
System.out.println("固定周期指定任务");
}, Duration.ofSeconds(2)); // every 2 sBy default Spring Boot creates a ThreadPoolTaskScheduler with a single thread, which may cause task queuing when multiple jobs overlap. You can enlarge the pool via configuration:
spring:
task:
scheduling:
thread-name-prefix: pack-task
pool:
size: 2The property spring.task.scheduling.pool.size defaults to 1 .
2. Annotation‑Based Scheduling
The most common way to define scheduled jobs is with @Scheduled annotations. Example of a fixed‑delay task:
@Scheduled(fixedDelay = 2000)
public void fixedDelayTask() throws Exception {
System.err.printf("Current Time: %s, Current Thread: %s%n",
new SimpleDateFormat("HH:mm:ss").format(new Date()),
Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
}Even though the delay is set to 2 s, the actual interval becomes 3 s because the execution time (1 s) is added.
Using a cron expression:
@Scheduled(cron = "*/3 * * * * *")
public void task1() {
// TODO
}This runs every 3 seconds.
3. Reactive Support
Since Spring Framework 6.1, reactive methods can also be scheduled:
@Scheduled(fixedRate = 2, timeUnit = TimeUnit.SECONDS)
public Flux<Integer> reactiveTask() {
return Flux.just(1, 2, 3).doOnNext(System.err::println);
}The method prints 1, 2, 3 every 2 seconds.
4. Cron Expressions and Macros
A standard cron expression consists of six space‑separated fields. Spring supports macros for common schedules, e.g., @hourly instead of 0 0 * * *. The table below shows the macros:
Macro
Description
@yearly (or @annually)
once a year (0 0 0 1 1 *)
@monthly
once a month (0 0 0 1 * *)
@weekly
once a week (0 0 0 * * 0)
@daily (or @midnight)
once a day (0 0 0 * * *)
@hourly
once an hour (0 0 * * *)
Example using a macro:
@Scheduled(cron = "@hourly")
public void task2() {
System.out.println("宏指令执行任务");
}5. Virtual Thread Support
From Spring 6.1 (JDK 21) you can enable virtual threads for scheduled tasks:
spring:
threads:
virtual:
enabled: trueExample:
@Scheduled(cron = "*/3 * * * * *")
public void scheduler1() throws Exception {
System.err.printf("当前时间: %s, 当前线程: %s, 是否虚拟线程: %b%n",
new SimpleDateFormat("HH:mm:ss").format(new Date()),
Thread.currentThread().getName(),
Thread.currentThread().isVirtual());
}When virtual threads are used, the traditional thread‑pool size configuration becomes irrelevant.
6. Custom Scheduling Configuration
Implement SchedulingConfigurer to provide a custom TaskScheduler bean:
@Component
public class PackSchedulingConfigurer implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("my-task-");
taskScheduler.afterPropertiesSet();
taskRegistrar.setTaskScheduler(taskScheduler);
}
}You can also register tasks programmatically:
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addCronTask(() -> {
System.out.println("动态注册调度任务...");
}, "*/2 * * * * *");
}These snippets demonstrate how to tailor the scheduling infrastructure to specific needs.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
