Backend Development 7 min read

Run a Spring Boot Scheduled Task Only Once – Practical Code Guide

This article explains how to configure a Spring Boot scheduled task to execute just once, covering three approaches—specifying a start time with TaskScheduler, using @Scheduled with an initial delay, and creating a custom PeriodicTrigger—complete with runnable code examples.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Run a Spring Boot Scheduled Task Only Once – Practical Code Guide

In this article we learn how to control a scheduled task so that it runs only once in a Spring Boot 3.2.5 application. While @Scheduled is convenient for recurring jobs, sometimes a one‑time execution is required, such as initializing resources or performing a data migration.

1. Introduction

We will explore several methods to achieve a single‑run task, ranging from using @Scheduled with an initial delay to leveraging TaskScheduler and custom triggers.

2. Practical Cases

2.1 Specify a Start Time with TaskScheduler

The @Scheduled annotation lacks flexibility for one‑time tasks. By using Spring's TaskScheduler we can programmatically schedule a Runnable to run at a specific Instant :

<code>public class TaskComponent {
  private TaskScheduler taskScheduler = new SimpleAsyncTaskScheduler();

  public void schedule(Runnable task, Instant startTime) {
    taskScheduler.schedule(task, startTime);
  }
}
</code>

This method is ideal because all other TaskScheduler methods are intended for periodic execution.

Note: The example uses SimpleAsyncTaskScheduler . In Spring 6.1+ you can enable virtual threads:

<code>SimpleAsyncTaskScheduler scheduler = new SimpleAsyncTaskScheduler();
scheduler.setVirtualThreads(true);
</code>

A unit test can verify the one‑time execution:

<code>@Test
public void testOnceTask() throws Exception {
  CountDownLatch cdl = new CountDownLatch(1);
  scheduler.schedule(() -> {
    cdl.countDown();
    // TODO: task action
  }, Instant.now().plus(Duration.ofSeconds(1)));
  cdl.await();
}
</code>

2.2 Using @Scheduled with Initial Delay

Another option is to use the @Scheduled annotation with initialDelay while omitting fixedDelay or fixedRate :

<code>@Component
public class TaskComponent {
  @Scheduled(initialDelay = 3000)
  public void task() {
    // TODO: task action
  }
}
</code>

This runs the task once after a 3‑second delay and does not repeat.

2.3 Custom Trigger with PeriodicTrigger

For maximum control we can implement a custom trigger by extending PeriodicTrigger and overriding nextExecution() to return null after the first execution:

<code>public class PackTrigger extends PeriodicTrigger {
  public PackTrigger(Instant when) {
    super(Duration.ofSeconds(1));
    Duration difference = Duration.between(Instant.now(), when);
    setInitialDelay(difference);
  }

  @Override
  public Instant nextExecution(TriggerContext triggerContext) {
    if (triggerContext.lastCompletion() == null) {
      return super.nextExecution(triggerContext);
    }
    // Returning null stops further executions
    return null;
  }
}
</code>

Using this trigger:

<code>TaskScheduler taskScheduler = new SimpleAsyncTaskScheduler();
taskScheduler.schedule(() -> {
  System.out.printf("%s, executing task%n", Thread.currentThread().getName());
}, new PackTrigger(Instant.now().plusSeconds(2)));
</code>

This custom trigger provides the most flexible way to ensure a scheduled task runs only once.

Below are two illustrative images from the original article:

Javabackend developmentSpring BootScheduled TaskTaskSchedulerCustom Trigger
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.