I am using the @Scheduled
annotation from Spring framework to invoke a method. But I have multiple nodes in my setup and I do not want them to all run at exactly the same time. So I'd like to set a random value to the initial delay to offset them from each other.
import org.springframework.scheduling.annotation.Scheduled;
@Scheduled(fixedRate = 600000, initialDelay = <random number between 0 and 10 minutes> )
Unfortunately, I am only allowed to use a constant expression here. Is there any other way around this? I thought of using Spring expression language.
The @EnableScheduling annotation is used to enable the scheduler for your application. This annotation should be added into the main Spring Boot application class file. @SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.
We can turn any method in a Spring bean for scheduling by adding the @Scheduled annotation to it. The @Scheduled is a method-level annotation applied at runtime to mark the method to be scheduled. It takes one attribute from cron , fixedDelay , or fixedRate for specifying the schedule of execution in different formats.
Initial delay is a period of time that Scheduler is waiting for before the configured task is executed. InitialDelay is a element in @Scheduled annotation that is added to a method.
Schedule a Task at Fixed Delay In this case, the duration between the end of the last execution and the start of the 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.
You can configure the initialDelay through Spring Expression Language:
@Scheduled(fixedRate = 600000, initialDelayString = "#{ T(java.util.concurrent.ThreadLocalRandom).current().nextInt(10*60*1000) }" )
I don't have an IDE to test that code right now, so you may need to adapt that a bit.
To make the initial delay randomly somewhere between 0 and the fixedRate
try this:
@Scheduled(fixedDelayString = "${some.delay}", initialDelayString = "${random.int(${some.delay})}")
Where you define some.delay
(but pick a more suitable name) as 10 minutes as a property like so in your application.properties or equivalent.
some.delay = 600000
Of course if you want to be lazy and hard code it you can always just use ${random.int(600000)}
In this working example, the random delay will be between 5 and 10 seconds.
@Scheduled(fixedDelayString = "#{new Double((T(java.lang.Math).random() + 1) * 5000).intValue()}")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With