1. Introduction
In this tutorial, We'll learn how to run scheduled jobs in Spring Boot. There are some scenarios, you need to perform some tasks periodically at a fixed interval of time. Spring boot provides mainly with @Scheduled fixedRate and fixedDelay attributes.
In fact, Spring Boot bundled with two annotations those support scheduling at a given time.
@EnableScheduling and @Scheduled annotations do the job in spring boot.
First, @EnableScheduling should be applied to the SpringBootApplication.
Next, @Scheduled must be applied on any method but that method should not take any arguments and should not return any value hence void should be return type.
2. Enabling Scheduling in Spring Boot Main Application
In spring boot, You have to tell that scheduling and all of its configurations are required. Because by default it is disabled so you must use @EnableScheduling annotation in the main SpringBootApplication as following.
package com.javaprogramto.schedulingjobs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class SchedulingJobsApplication {
public static void main(String[] args) {
SpringApplication.run(SchedulingJobsApplication.class, args);
}
}
Once, the application started then it will show on the console saying taskScheduler related stuff has been initialized and internally it invokes @Import(SchedulingConfiguration.class) instruction.
Initializing ExecutorService 'taskScheduler'
3. @Scheduled Annotation - Schedule a Task at Fixed Rate
Let us now create a job that will run at a fixed rate. For this, you must use @Scheduled annotation and fixedRate property on the method which has to be run for every 5 seconds.
As I told earlier, @Scheduled annotated method should take no arguments and void return type.
@Scheduled(fixedRate = 5 * 1000)
public void atFixedRate() throws InterruptedException {
logger.info("Current thread name : " + Thread.currentThread().getName() + " started");
Thread.sleep(6 * 1000);
logger.info("Current thread name : " + Thread.currentThread().getName() + " ended");
}
Once you start the application than immediately this job will be picked by the task scheduler. We have written the job to run at fixed rate for every 5 seconds and added sleep for 6 seconds inside task. As well as priting the current execution thread name. Let us see the loggers in the output.
2020-04-26 00:10:12.125 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 started
2020-04-26 00:10:18.130 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 ended
2020-04-26 00:10:18.130 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 started
2020-04-26 00:10:24.134 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 ended
2020-04-26 00:10:24.134 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 started
2020-04-26 00:10:30.139 INFO 65801 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : Current thread name : scheduling-1 ended
Here, always only one thread is running at a time and after completion of the current run then only it starts the next run even though each run takes 6 seconds whereas the run rate is 5 seconds.
So, Spring Boot ensures that it will not run the next cycle untill it completes the previous run.
If the previous run throws an exception then it terminates the current run and starts the next run. Throwing an exception will not prevent the next runs from execution.
4. @Scheduled Annotation - Schedule a Task at Fixed Delay
Along with the fixedRate, @Scheduled annotation has another attribute "fixedDelay" which also takes the time in milliseconds.
Many developers think that fixedRate and fixedDelay are the same but there is a difference you should know that before using it in the wrong place.
But, Before seeing the fixedRate VS FixedDelay first see the example program on this.
@Scheduled(fixedDelay = 5 * 1000)
public void atFixedDelay() throws InterruptedException {
logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " started");
Thread.sleep(5 * 1000);
logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " ended");
//throw new RuntimeErrorException(null, "..");
}
Here, the scheduled job for every 5 seconds and job needs 5 seconds to complete.
Output:
From the logs, you can see that after completion of each job scheduler is sleeping for 5 seconds and starts the next run.
2020-04-26 15:16:32.687 INFO 71113 --- [ main] o.s.s.c.ThreadPoolTaskScheduler : Initializing ExecutorService 'taskScheduler'
2020-04-26 15:16:32.700 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 started
2020-04-26 15:16:32.706 INFO 71113 --- [ main] c.j.s.SchedulingJobsApplication : Started SchedulingJobsApplication in 1.208 seconds (JVM running for 1.859)
2020-04-26 15:16:37.703 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 ended
2020-04-26 15:16:42.708 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 started
2020-04-26 15:16:47.712 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 ended
2020-04-26 15:16:52.715 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 started
2020-04-26 15:16:57.716 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 ended
2020-04-26 15:17:02.719 INFO 71113 --- [ scheduling-1] c.j.schedulingjobs.SchedulingJobs : fixedDelay Current thread name : scheduling-1 started
5. @Scheduled fixedRate VS fixedDelay
Here are the main differences between fixeDelay and fixedRate.
@Scheduled annotation has mainly two attributes fixedRate and fixedDelay. Both work well in executing a task periodically. But, based on the properties fixedDelay and fixedRate the nature of execution changes.
The fixedDelay property makes sure that always there is a delay of n milliseconds after every run. That means the dealy is between after finishing the job and starting the next job.
Additionally, this property is most important if you want to see that only running one instance of the task at any point in time. So, It is good to go with a fixedDelay attribute or property.
And also if you do not know how much time this job runs sometimes it may take 2hours or 2 mins then it is better to go for fixed delay mode. So that, it can sleep for n milliseconds and start the next task run.
Whereas fixedRate property makes sure that the job runs for every n milliseconds and it does not check previous run status. If you have enabled to run the tasks parallelly then it does not check for the previous run whether it is successful. Further, It simply runs the next task after n milliseconds.
Most importantly, this fixedRate property does not work if tasks are dependent on each other and work well for only independent jobs. And also you have to keep in mind that this needs lots of memory if there are a high number of parallel tasks. For example, a task takes 1 hrs time to complete and it creates lots of objects but it is configured to run for every 2 mins then it creates around 30 tasks parallel and consumes a huge amount of memory. So, you have to balance the running interval such a way to reduce memory unnecessary utilization.
In the worst case, if all tasks complete the jobs in time then the application will end up in OutOfMemeoryException that indicating that the Heap memory is full.
6. @Async Running Parallel Taks
If you tasks that can be run simultaneously and next job not needed output of the previous run then you can use @EnableAync power in Spring Boot.
To achieve parallel task execution capability, your scheduling class must be annotated with @EnableAsync annotation which enables running multiple tasks at a time.
Please take a note on this, once you enable @EnableAsync annotation then @Scheduled annotation is not required because in inturn it gets all abilities if Scheduler jobs.
In Async jobs, fixedDelay will not give parallel capability. So, you must have to use only fixedRate property along with @async annotation on the method level.
Scheduling Parallel Tasks Example
@Component
@EnableAsync
public class AsyncJobs {
private Logger logger = LoggerFactory.getLogger(getClass());
@Async
@Scheduled(fixedRate = 1 * 1000)
public void runParallelJobs() throws InterruptedException {
logger.info("Current thread name : " + Thread.currentThread().getName() + " started");
Thread.sleep(3 * 1000);
logger.info("Current thread name : " + Thread.currentThread().getName() + " ended");
}
}
Jobs is configured to run for every 1 minute but the job will complete in 3 mins. After every 1 minute, schedular creates another task even though previous jobs were not completed.
As a result, it started 4 threads before completion of the first task as per the log.
Output:
2020-04-26 16:40:36.956 INFO 74218 --- [ task-1] c.j.schedulingjobs.AsyncJobs : Current thread name : task-1 started
2020-04-26 16:40:37.934 INFO 74218 --- [ task-2] c.j.schedulingjobs.AsyncJobs : Current thread name : task-2 started
2020-04-26 16:40:38.938 INFO 74218 --- [ task-3] c.j.schedulingjobs.AsyncJobs : Current thread name : task-3 started
2020-04-26 16:40:39.932 INFO 74218 --- [ task-4] c.j.schedulingjobs.AsyncJobs : Current thread name : task-4 started
2020-04-26 16:40:39.957 INFO 74218 --- [ task-1] c.j.schedulingjobs.AsyncJobs : Current thread name : task-1 ended
2020-04-26 16:40:40.934 INFO 74218 --- [ task-5] c.j.schedulingjobs.AsyncJobs : Current thread name : task-5 started
2020-04-26 16:40:40.937 INFO 74218 --- [ task-2] c.j.schedulingjobs.AsyncJobs : Current thread name : task-2 ended
2020-04-26 16:40:41.936 INFO 74218 --- [ task-6] c.j.schedulingjobs.AsyncJobs : Current thread name : task-6 started
2020-04-26 16:40:41.939 INFO 74218 --- [ task-3] c.j.schedulingjobs.AsyncJobs : Current thread name : task-3 ended
2020-04-26 16:40:42.936 INFO 74218 --- [ task-4] c.j.schedulingjobs.AsyncJobs : Current thread name : task-4 ended
2020-04-26 16:40:42.936 INFO 74218 --- [ task-7] c.j.schedulingjobs.AsyncJobs : Current thread name : task-7 started
2020-04-26 16:40:43.934 INFO 74218 --- [ task-5] c.j.schedulingjobs.AsyncJobs : Current thread name : task-5 ended
2020-04-26 16:40:43.935 INFO 74218 --- [ task-8] c.j.schedulingjobs.AsyncJobs : Current thread name : task-8 started
2020-04-26 16:40:44.934 INFO 74218 --- [ task-1] c.j.schedulingjobs.AsyncJobs : Current thread name : task-1 started
2020-04-26 16:40:44.940 INFO 74218 --- [ task-6] c.j.schedulingjobs.AsyncJobs : Current thread name : task-6 ended
2020-04-26 16:40:45.934 INFO 74218 --- [ task-2] c.j.schedulingjobs.AsyncJobs : Current thread name : task-2 started
2020-04-26 16:40:45.939 INFO 74218 --- [ task-7] c.j.schedulingjobs.AsyncJobs : Current thread name : task-7 ended
7. Schedule a Task With Initial Delay
Let us jump into another small section on how to add an initial delay only at the beginning of the first task and not for all consequent tasks.
In this example, we have used initialDelay with fixedDelay and fixedRate properties. You can choose based on your needs.
7.1 fixedDelay + initialDelay
@Scheduled(fixedDelay = 2 * 1000, initialDelay = 2 * 2000)
public void initialDelayFixedDelay() {
logger.info("initialDelayFixedDelay Current thread name : " + Thread.currentThread().getName() + " started");
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
logger.error("interrupted..");
}
logger.info("initialDelayFixedDelay Current thread name : " + Thread.currentThread().getName() + " ended");
}
7.2 fixedRate + fixedRate
@Scheduled(fixedRate = 2 * 1000, initialDelay = 2 * 2000)
public void initialDelayFixedRate() {
logger.info("initialDelayFixedRate Current thread name : " + Thread.currentThread().getName() + " started");
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
logger.error("interrupted..");
}
logger.info("initialDelayFixedRate Current thread name : " + Thread.currentThread().getName() + " ended");
}
This is useful if you want to complete all the setup and configurations before starting the actual job.
8. Schedule a Task Using Cron Expressions
Sometimes there is a need that we are going to remove jobs from control-m and moving them to as part of the app because of heavy maintenance.
And also this provides a most flexible way to define our interval time such as job should be run for every Monday, Wednesday and Friday morning at 2AM
You should use cron property on @Scheduled annotation that takes cron pattern as String.
@Scheduled(cron = "0 0 2 * * 1,3,5")
public void cronpattern() {
logger.info("cronpattern Current thread name : " + Thread.currentThread().getName() + " started");
logger.info("cronpattern Current thread name : " + Thread.currentThread().getName() + " ended");
}
9. Parameterizing the Schedule
Actually, In the realtime application, you should not use all these time schedules as hardcoded values. If you do so then you need to recompile and redeploy the application which is time taking and tedious process.
To avoid all of these places these schedules in the external configuration files such that you can avoid recompiling and deployment. Hence, simply you can do just restarting the application should be fine and easy to maintain the application with fewer changes.
@Schedule annotation has another two properties that take strings as values.
String accepted properties are fixedRateString and fixedDelayString whereas cron takes always String value.
@Scheduled(fixedRateString = "${fixed-rate-time-in-milliseconds}")
public void fixedRate() {
logger.info("running fixedRate task");
}
@Scheduled(fixedDelayString = "${fixed-delay-time-in-milliseconds}")
public void fixedDelay() {
logger.info("running fixedDelay task");
}
@Scheduled(cron = "${cron-pattern-time-in-milliseconds}")
public void cron() {
logger.info("running cron task");
}
10. With @Scheduled method arguments and return type
If you pass some values to the @Scheduled method then it throws the following runtime exception saying "Only no-arg methods may be annotated with @Scheduled".
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulingJobs' defined in file [/Users/venkateshn/Documents/VenkY/blog/workspace/spring-boot-scheduling-jobs/target/classes/com/javaprogramto/schedulingjobs/SchedulingJobs.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid @Scheduled method 'cronpattern': Only no-arg methods may be annotated with @Scheduled
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at com.javaprogramto.schedulingjobs.SchedulingJobsApplication.main(SchedulingJobsApplication.java:14) [classes/:na]
Caused by: java.lang.IllegalStateException: Encountered invalid @Scheduled method 'cronpattern': Only no-arg methods may be annotated with @Scheduled
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.processScheduled(ScheduledAnnotationBeanPostProcessor.java:499) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$null$1(ScheduledAnnotationBeanPostProcessor.java:362) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_161]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.lambda$postProcessAfterInitialization$2(ScheduledAnnotationBeanPostProcessor.java:362) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_161]
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:361) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:431) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 14 common frames omitted
No exception will be thrown if the @Schedule method returns some value. The below code worked fine and tested.
@Scheduled(fixedRate = 2 * 1000, initialDelay = 2 * 2000)
public String initialDelayFixedRate() {
return "done";
}
11. Conclusion
In this article, You've seen in-depth article on How to schedule jobs in the spring boot framework.
How to schedule jobs at fixed intervals and fixed delay timings. And also how to configure async parallel jobs and these fit only for independent jobs.
Finally, how to use cron pattern also with @Scheduled annotation and possible runtime exceptions.
As usual, all the code shown in this article is over Github.
[View on GitHub ##eye##]
[Download ##file-download##]
- [accordion]
- SchedulingJobsApplication.java
package com.javaprogramto.schedulingjobs; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling @PropertySource("classpath:spring/external.properties") public class SchedulingJobsApplication { public static void main(String[] args) { SpringApplication.run(SchedulingJobsApplication.class, args); } }
- SchedulingJobs.java
package com.javaprogramto.schedulingjobs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component public class SchedulingJobs { private Logger logger = LoggerFactory.getLogger(getClass()); // @Scheduled(fixedRate = 5 * 1000) public void atFixedRate() throws InterruptedException { logger.info("Current thread name : " + Thread.currentThread().getName() + " started"); Thread.sleep(6 * 1000); logger.info("Current thread name : " + Thread.currentThread().getName() + " ended"); // throw new RuntimeErrorException(null, ".."); } // @Scheduled(fixedDelay = 3 * 1000) public void atFixedDelay() throws InterruptedException { logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " started"); Thread.sleep(1 * 1000); logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " ended"); // throw new RuntimeErrorException(null, ".."); } //@Scheduled(fixedDelay = 2 * 1000, initialDelay = 2 * 2000) public void initialDelayFixedDelay() { logger.info("initialDelayFixedDelay Current thread name : " + Thread.currentThread().getName() + " started"); try { Thread.sleep(2 * 1000); } catch (InterruptedException e) { logger.error("interrupted.."); } logger.info("initialDelayFixedDelay Current thread name : " + Thread.currentThread().getName() + " ended"); } @Scheduled(fixedRate = 2 * 1000, initialDelay = 2 * 2000) public String initialDelayFixedRate() { logger.info("initialDelayFixedRate Current thread name : " + Thread.currentThread().getName() + " started"); try { Thread.sleep(1 * 1000); } catch (InterruptedException e) { logger.error("interrupted.."); } logger.info("initialDelayFixedRate Current thread name : " + Thread.currentThread().getName() + " ended"); return ""; } @Scheduled(cron = "0 0 2 * * 1,3,5") public void cronpattern() { logger.info("cronpattern Current thread name : " + Thread.currentThread().getName() + " started"); logger.info("cronpattern Current thread name : " + Thread.currentThread().getName() + " ended"); } }
- ParameterSchedules.java
package com.javaprogramto.schedulingjobs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; //@Component public class ParameterSchedules { private Logger logger = LoggerFactory.getLogger(getClass()); @Scheduled(fixedRateString = "${fixed-rate-time-in-milliseconds}") public void fixedRate() { logger.info("running fixedRate task"); } @Scheduled(fixedDelayString = "${fixed-delay-time-in-milliseconds}") public void fixedDelay() { logger.info("running fixedDelay task"); } @Scheduled(cron = "${cron-pattern-time-in-milliseconds}") public void cron() { logger.info("running cron task"); } }
- AsyncJobs.java
package com.javaprogramto.schedulingjobs; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; //@Component @EnableAsync public class AsyncJobs { private Logger logger = LoggerFactory.getLogger(getClass()); @Async @Scheduled(fixedRate = 1 * 1000) public void runParallelJobs() throws InterruptedException { logger.info("Current thread name : " + Thread.currentThread().getName() + " started"); Thread.sleep(3 * 1000); logger.info("Current thread name : " + Thread.currentThread().getName() + " ended"); } // @Async // @Scheduled(fixedDelay = 3 * 1000) public void atFixedDelayAsync() throws InterruptedException { logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " started"); Thread.sleep(1 * 1000); logger.info("fixedDelay Current thread name : " + Thread.currentThread().getName() + " ended"); } // @Async // @Scheduled(fixedRate = 5 * 1000) public void atFixedRateAsync() throws InterruptedException { logger.info("Current thread name : " + Thread.currentThread().getName() + " started"); Thread.sleep(10 * 1000); logger.info("Current thread name : " + Thread.currentThread().getName() + " ended"); } }
- spring/external.properties
# 10 mins fixed-rate-time-in-milliseconds=10 * 1000 # 2 mins fixed-delay-time-in-milliseconds=2 * 1000 # 5 mins cron-pattern-time-in-milliseconds=5 * 1000
No comments:
Post a Comment
Please do not add any spam links in the comments section.