I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this article we’ll discuss the Spring @Scheduled annotation – we will illustrate how it can be used to configure and schedule tasks.

The simple rules that need to be followed to annotate a method with @Scheduled are:

  • a method should have void return type
  • a method should not accept any parameters

Further reading:

How To Do @Async in Spring

How to enable and use @Async in Spring - from the very simple config and basic usage to the more complex executors and exception handling strategies.

Read more

A Guide to the Spring Task Scheduler

A quick and practical guide to scheduling in Spring with Task Scheduler

Read more

Scheduling in Spring with Quartz

Quick introduction to working with Quartz in Spring.

Read more

2. Enable Support for Scheduling

To enable the support for scheduling tasks and the @Scheduled annotation in Spring – we can use the Java enable-style annotation:

@Configuration
@EnableScheduling
public class SpringConfig {
    ...
}

Or we can do the same in XML:

<task:annotation-driven>

3. Schedule a Task at Fixed Delay

Let’s start by configuring a task to run after a fixed delay:

@Scheduled(fixedDelay = 1000)
public void scheduleFixedDelayTask() {
    System.out.println(
      "Fixed delay task - " + System.currentTimeMillis() / 1000);
}

In this case, the duration between the end of last execution and the start of next execution is fixed. The task always waits until the previous one is finished.

This option should be used when it’s mandatory that the previous execution is completed before running again.

4. Schedule a Task at a Fixed Rate

Let’s not execute a task at a fixed interval of time:

@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTask() {
    System.out.println(
      "Fixed rate task - " + System.currentTimeMillis() / 1000);
}

Note that the beginning of the task execution doesn’t wait for the completion of the previous execution.

This option should be used when each execution of the task is independent.

5. Schedule a Task with Initial Delay

Next – let’s schedule a task with a delay (in milliseconds):

@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void scheduleFixedRateWithInitialDelayTask() {
 
    long now = System.currentTimeMillis() / 1000;
    System.out.println(
      "Fixed rate task with one second initial delay - " + now);
}

Note how we’re using both fixedDelay as well as initialDelay in this example. The task will be executed a first time after the initialDelay value – and it will continue to be executed according to the fixedDelay.

This option comes handy when the task has a set-up that needs to be completed.

6. Schedule a Task using Cron Expressions

Sometimes delays and rates are not enough, and we need the flexibility of a cron expression to control the schedule of our tasks:

@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
 
    long now = System.currentTimeMillis() / 1000;
    System.out.println(
      "schedule tasks using cron jobs - " + now);
}

Note – in this example, that we’re scheduling a task to be executed at 10:15 AM on the 15th day of every month.

7. Parameterizing the Schedule

Hardcoding these schedules is simple, but usually, you need to be able to control the schedule without re-compiling and re-deploying the entire app.

We’ll make use of Spring Expressions to externalize the configuration of the tasks – and we’ll store these in properties files:

A fixedDelay task:

@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds}")

A fixedRate task:

@Scheduled(fixedRateString = "${fixedRate.in.milliseconds}")

A cron expression based task:

@Scheduled(cron = "${cron.expression}")

8. Configuring scheduled tasks using XML

Spring also provides XML way of configuring the scheduled tasks – here is the XML configuration to set these up:

<!-- Configure the scheduler -->
<task:scheduler id="myScheduler" pool-size="10" />

<!-- Configure parameters -->
<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="beanA" method="methodA" 
      fixed-delay="5000" initial-delay="1000" />
    <task:scheduled ref="beanB" method="methodB" 
      fixed-rate="5000" />
    <task:scheduled ref="beanC" method="methodC" 
      cron="*/5 * * * * MON-FRI" />
</task:scheduled-tasks>

9. Conclusion

In this article, we understood the way to configure and use the @Scheduled annotation.

We covered the process to enable scheduling and various ways of configuring scheduling task patterns.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Notify of
Ali
Guest
Ali

Hi,

Could you suggest, any way to test these schedules tasks please ?

Many thanks

Eugen Paraschiv
Guest

Hey Ali,
When it comes to testing, my suggestion is to test the logic inside these tasks normally – not the actual triggering of the task. The reason for that is – you want to test your own logic, not test the framework (that’s already well tested).
Cheers,
Eugen.

Ali
Guest
Ali

Good catch.
Thanks Eugen. I really appreciate your prompt reply.

Mátyás Albert Nagy
Guest
Mátyás Albert Nagy

Hey Eugen!

Would you happen to know a way to disable scheduled tasks during integration tests?

Thanks & Cheers,
m

Eugen Paraschiv
Guest

The easiest way to do that is simply make sure that the test does loads up the configuration where you have the @EnableScheduling annotation defined. Tests can pick and chose exactly what configuration they’re using when they’re bootstrapping the context, and that’s exactly the reason you have that option and flexibility.
Hope that helps. Cheers,
Eugen.

Sergio Polo Galiano
Guest
Sergio Polo Galiano

Hi,

I used quartz framework to schedule tasks in a cluster-based environment. It saves the information on database of triggers and cronexpressions used in that scheduling, to save the state and avoid conflicts between the different nodes where the application is running.

Is possible to configure scheduled tasks in a cluster-based environment with this annotation technique you describe in the article?

Eugen Paraschiv
Guest

Last time I checked the Spring-Quartz integration – no, you couldn’t use the @Scheduled annotation and delegate to Quartz. That was a while back though, so things might have changed.

Sergio Polo Galiano
Guest
Sergio Polo Galiano

Thanks for your reply!
I will investigate for it. If I found something interesting, I will post here.

Eugen Paraschiv
Guest

Cool Sergio – I’m curious as well. And, of course – you can always write about it here on Baeldung 🙂
Cheers,
Eugen.

Jeffrey Naujok
Guest
Jeffrey Naujok

So, I have a question about the @Scheduled — we use it to run a background process, but when we shut down the main thread, I end up with a thread hanging named “background.scheduled.timer”. I’m assuming this is the Scheduler thread Spring uses to run these tasks. However, it’s not marked as a Daemon thread, so it prevents the application from shutting down gracefully.

Is this a known issue? Is there a work-around? Thanks.

Got the master class, but I’m not very far into it yet.

Eugen Paraschiv
Guest

Hey Jeffrey,
To make sure things properly shut down, you’ll need to shut them down explicitly. You can have shutdown logic running at the closing of the Spring context and simply call shutdown on both the executor and the scheduler. Here’s a quick video to help you set up some of that logic (not specifically focused on the scheduler, but the concept is the same).
Glad you’re enjoying the course. Cheers,
Eugen.

Jeffrey Naujok
Guest
Jeffrey Naujok

Thanks for the quick response. Our resident Spring expert actually chased down an alternative about 10 minutes before you responded though:

The principal line being, of course, the “daemon” set to “true” in which case, when the rest of the non-daemon threads shut down, the scheduler thread shuts down with it.

Eugen Paraschiv
Guest

Looks like a good alternative 🙂 – so it’s sorted – cool. Cheers,
Eugen.

Carlos De Oliveira
Guest
Carlos De Oliveira

Hi, What happen if the Scheduled Method takes more time that the fixed delay ? There is a way to lock the method to avoid concurrence ?

Eugen Paraschiv
Guest

Well, methods in Java are reentrant, so it’s simply going to run again. Adding syncronization semantics around it (or aborting it) – definitely worth exploring.
But if you’re doing that, it might be more beneficial to use an actual thread pool/executor where you have a lot more control over what’s going on.

Dipesh Rane
Guest
Dipesh Rane

Can I attach timezone to cron expressions ? My servers are running in Singapore region but I might have to trigger scheduled task at midnight of different timezone.

Eugen Paraschiv
Guest

Hey Dipesh – no, as far as I’m aware you can’t. However, I haven’t looked to much into it, it may still be worth looking at the expression syntax to see if there’s support for that.
Cheers,
Eugen.

Steve Cancès
Guest
Steve Cancès
Eugen Paraschiv
Guest

That’s cool, I wasn’t aware of that one. Cheers,
Eugen

Mira
Guest
Mira

Have you looked at the ‘zone’ annotation attribute, it seems to do exactly what you need.