In writing Spring Boot applications, we often encounter such scenarios, such as: I need to regularly send some SMS, email and other operations, may also periodically check and monitor some flags, parameters, and so on.
Create a timed task
It is very easy to write a timer task in Spring Boot. Here is an example of how to create a timer task in Spring Boot. It outputs the current time every 5 seconds.
- In the main class of Spring Boot
@EnableScheduling
Comments that enable the configuration of timed tasks
@SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
- Create a timed task implementation class
@Component public class ScheduledTasks { private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); Scheduled(FIXEDRate = 5000) public void ReportCurrentTime () {log.info(" Scheduled: "+ dateFormat (new Date()))); }}
- Run the program and you will see output similar to the following in the console. Timing task is now working normally.
The 14:56:56 2021-07-13. 34836-413 the INFO [main] C.D.C. hapter71. Chapter71Application: Started Chapter712 Application in 1.457 Seconds (JVM running for 1.435) 2021-07-13 14:57:01.411 INFO 34836 -- [ scheduling-1] com.didispace.chapter71.ScheduledTasks : Now time: 14:57:01 14:57:06 2021-07-13. 34836-412 the INFO] [the scheduling - 1 com. Didispace. Chapter71. ScheduledTasks: Now time: 14:57:06 14:57:11 2021-07-13. 34836-413 the INFO] [the scheduling - 1 com. Didispace. Chapter71. ScheduledTasks: Now time: 14:57:11 14:57:16 2021-07-13. 34836-413 the INFO] [the scheduling - 1 com. Didispace. Chapter71. ScheduledTasks: Time: 14:57:16
@Scheduled
Break down
In the introductory example above, the @Scheduled(FixedRate = 5000) annotation was used to define the task to execute every 5 seconds. For the use of @scheduled, let’s take a look at the configuration from the source code:
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;
String cron() default "";
String zone() default "";
long fixedDelay() default -1;
String fixedDelayString() default "";
long fixedRate() default -1;
String fixedRateString() default "";
long initialDelay() default -1;
String initialDelayString() default "";
}
The meaning of this specific configuration information is as follows:
- Cron: Configure execution rules through cron expressions
- Zone: The time zone used when the cron expression is parsed
- FixedDelay: The amount of time (in ms) between the end of the last execution and the start of the next.
- FixedDelayString: The time between the end of the last task execution and the start of the next, resolved using java.time.duration# parse
- FixedRate: executes a task at a fixed interval, that is, the interval time between the start of the last task execution and the start of the next one (unit: ms). If the last task is not completed when the task is scheduled, it will be added to the Worker queue and wait for the next task to be executed immediately after the completion of the last task execution
- FixedRateString: Same as FixedRate logic, only using java.time.duration# parse parse
- InitialDelay: The delay time for the first task execution
- InitialDelayString: The delay time for the first task execution, resolved using java.time.duration# parse
Thinking and advancement
Is it easy to implement timed tasks in this way? So let’s go ahead and think about if there are any drawbacks to this implementation.
It may not be easy for beginners to see the problem, but if you already have some experience with online projects, the problem is obvious: this mode implements timed tasks that lack coordination mechanisms in a clustered environment.
What does that mean? Suppose we want to implement a timed task that counts data on the web each day and adds it to the raw data. We don’t have a problem developing tests because they are all run by a single process. However, when we deploy such a timed task to a production environment, it is necessary to start multiple instances for higher availability. At this point, as soon as the time is up, all started instances will start executing the task at the same time. And that’s where the problem comes in, because we’re summing things up, and we’re going to end up with a problem.
The way to solve the problem of such a lot of kinds, more common is the way of using distributed lock, make similar tasks before time, in the form of a distributed lock to control execution order, such as: use Redis, Zookeeper have distributed lock function of middleware to cooperate can be very good to help us to coordinate this kind of task execution rules in cluster mode.
Other than that, do you have any good ways to solve it? Leave a comment! Spring Boot 2.x Fundamentals is still being updated. . If you encounter difficulties in the learning process, it is recommended to join the Spring technical communication group to participate in the communication and discussion, for better learning and progress!
Code sample
The complete project for this article can be viewed in the chapter7-1 directory in the repository below:
- Github:https://github.com/dyc87112/SpringBoot-Learning/
- Gitee:https://gitee.com/didispace/SpringBoot-Learning/
** If you think this article is good, welcome STAR support, your attention is the power I adhere to!
Welcome to pay attention to my official account: program ape DD, to share the knowledge and thinking that can not be seen elsewhere