Backend Development 8 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master Spring Boot 3 Task Scheduling: Interfaces, Annotations, Cron & Virtual Threads

1. TaskScheduler Interface

Spring provides a TaskScheduler SPI with methods for scheduling tasks. The core interface is:

<code>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);
}</code>

In a Spring Boot application you can inject it directly:

<code>@Resource
private TaskScheduler taskScheduler;

@PostConstruct
public void initScheduler() {
    this.taskScheduler.schedule(() -> {
        System.out.println("执行任务");
    }, new CronTrigger("*/2 * * * * *"));
}</code>

The above uses a cron expression to run every 2 seconds. You can also schedule at a fixed rate:

<code>this.taskScheduler.scheduleAtFixedRate(() -> {
    System.out.println("固定周期指定任务");
}, Duration.ofSeconds(2)); // every 2 s</code>

By 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:

<code>spring:
  task:
    scheduling:
      thread-name-prefix: pack-task
      pool:
        size: 2</code>

The 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:

<code>@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);
}</code>

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:

<code>@Scheduled(cron = "*/3 * * * * *")
public void task1() {
    // TODO
}</code>

This runs every 3 seconds.

3. Reactive Support

Since Spring Framework 6.1, reactive methods can also be scheduled:

<code>@Scheduled(fixedRate = 2, timeUnit = TimeUnit.SECONDS)
public Flux<Integer> reactiveTask() {
    return Flux.just(1, 2, 3).doOnNext(System.err::println);
}</code>

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:

<code>@Scheduled(cron = "@hourly")
public void task2() {
    System.out.println("宏指令执行任务");
}</code>

5. Virtual Thread Support

From Spring 6.1 (JDK 21) you can enable virtual threads for scheduled tasks:

<code>spring:
  threads:
    virtual:
      enabled: true</code>

Example:

<code>@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());
}</code>

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:

<code>@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);
    }
}</code>

You can also register tasks programmatically:

<code>public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    taskRegistrar.addCronTask(() -> {
        System.out.println("动态注册调度任务...");
    }, "*/2 * * * * *");
}</code>

These snippets demonstrate how to tailor the scheduling infrastructure to specific needs.

JavaBackend Developmenttask schedulingSpring BootVirtual Threadscron
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.