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:

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 s

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:

spring:
  task:
    scheduling:
      thread-name-prefix: pack-task
      pool:
        size: 2

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:

@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: true

Example:

@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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend 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

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.