Four ways Spring Boot implements timed tasks

Posted by rv20 on Wed, 10 Jun 2020 06:25:42 +0200

Author: Wan QingHua
wanqhblog.top/2018/02/01/SpringBootTaskSchedule/

Several ways to accomplish a timed task:

Timer: This comes with JavaJava.util.TimerClass, this class allows you to schedule aJava.util.TimerTaskTasks.This allows your program to execute at a certain frequency, but not at a specified time.Less commonly used.

ScheduledExecutorService: Also a class that comes with jdk; a timed task class based on a thread pool design, where each dispatch task is assigned to a thread in the thread pool to execute, that is, the task is executed concurrently without interacting with each other.

Spring Task: A task that comes with Spring 3.0 can be considered a lightweight Quartz and is much simpler to use than Quartz.

Quartz: This is a more powerful dispatcher that allows your program to execute at a specified time or at a certain frequency, which is slightly more complex to configure.

Use Timer

This is currently used less in projects, pasting demo code directly.Detailed description can see api

public class TestTimer {

   public static void main(String[] args) {

       TimerTask timerTask = new TimerTask() {
           @Override
           public void run() {
               System.out.println("task  run:"+ new Date());
           }

       };

       Timer timer = new Timer();

       //Schedule the specified task to start repeated, fixed delays at a specified time.This is executed every 3 seconds
       timer.schedule(timerTask,10,3000);
   }

}

Using Scheduled ExecutorService

This method is similar to Timer, looking directly at demo:

public class TestScheduledExecutorService {

   public static void main(String[] args) {

       ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

       // Parameters: 1, Task body 2, Delay time for first execution
       // 3. Task Execution Interval 4. Interval Units
       service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);

   }

}

Use Spring Task

Simple timed tasks

In SpringBoot projects, we can gracefully use annotations to accomplish timed tasks by first creating projects and importing dependencies:

<dependencies>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
 </dependency>

 <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
 </dependency>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
 </dependency>

</dependencies>

Create a task class:

@Slf4j

@Component

public class ScheduledService {

   @Scheduled(cron = "0/5 * * * * *")
   public void scheduled(){
       log.info("=====>>>>>Use cron  {}",System.currentTimeMillis());
   }

   @Scheduled(fixedRate = 5000)
   public void scheduled1() {
       log.info("=====>>>>>Use fixedRate{}", System.currentTimeMillis());
   }

   @Scheduled(fixedDelay = 5000)
   public void scheduled2() {
       log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());
   }

}

Use the @EnableScheduling annotation on the main class to turn on support for timed tasks, then start the project

Recommend: Spring Quick Start Program .You can see that all three timer tasks have been executed, and that they are executed serially in the same thread. If there is only one timer task, it will be OK to do so. When the timer tasks increase, if one task gets stuck, other tasks will not be executed.Focus on the Java technology stack WeChat Public Number and reply back to the keyword: spring, you can get more stack-length sorted Spring series technology dry goods.

Multithreaded Execution

In a traditional Spring project, we can add task configurations in the xml configuration file, whereas in a SpringBoot project, config configuration classes are generally used to add configurations, so create a new AsyncConfig class.Focus on the Java technology stack WeChat Public Number and reply back to the keyword: spring, you can get more stack-length sorted Spring series technology dry goods.

@Configuration
@EnableAsync
public class AsyncConfig {

    /*
     *Here member variables should be read from the configuration using @Value
    */
   private int corePoolSize = 10;
   private int maxPoolSize = 200;
   private int queueCapacity = 10;

   @Bean
   public Executor taskExecutor() {
       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       executor.setCorePoolSize(corePoolSize);
       executor.setMaxPoolSize(maxPoolSize);
       executor.setQueueCapacity(queueCapacity);
       executor.initialize();
       return executor;
   }

}

@Configuration: Indicates that the class is a configuration class
@EnableAsync: Turn on support for asynchronous events

Then add @Async to the class or method of the timed task.Finally, restart the project, each task in a different thread.

Configuration of execution time

In the timed task above, we use the @Scheduled annotation on the method to set the execution time of the task and use three attribute configurations:

fixedRate: Defines a timed task that is executed at a certain frequency

fixedDelay: Defines a fixed-time task that is executed at a certain frequency. Unlike above, changing attributes can work with initialDelay to define the delay in execution of the task.

cron: Configure task execution time by expression

Detailed cron expression

A cron expression has at least six (or possibly seven) space-delimited time elements.In order:

Seconds (0~59)

Minutes (0~59)

Hours (0~23)

Days (0~31)

Month (0~11)

Weeks (1-7 1 = SUN or SUN, MON, TUE, WED, THU, FRI, SAT)

Year (1970-2099)

Each element can be a value (such as 6), a continuous interval (9-12), an interval (8-18/4) (/every 4 hours), a list (1,3,5), and a wildcard.Since the "Date in Month" and "Date in Week" elements are mutually exclusive, one of them must be set.Recommend: Spring Quick Start Program.

**Configuration instance:
**

Execute every 5 seconds: /5 *?

Execute every 1 minute: 0/1?

0 0 10,14,16? Every day at 10 a.m., 2 p.m., 4 p.m.

0/309-17? Every half hour during 9:5 working hours

0 0 12? * WED means every Wednesday at 12:00 p.m.

"0 0 12?" Triggers every day at 12 noon

"0 15 10?" Triggers every day at 10:15 a.m.

"0 15 10?" Triggers every day at 10:15 a.m.

"0 1510?*" Triggers every day at 10:15 a.m.

"0 1510? 2005" Triggered every morning at 10:15 a.m. in 2005

"0 14 *?" Triggers every minute between 2 p.m. and 2:59 p.m. each day

"0/5 14?" Triggers every 5 minutes between 2 p.m. and 2:55 p.m. each day

"0/5 14,18?" Triggers every 5 minutes between 2 p.m. and 2:55 p.m. each day and between 6 p.m. and 6:55 p.m.

"0-5 14?" Triggers every minute between 2 p.m. and 2:05 p.m. each day

"0 10,44 14? 3 WED" is triggered every March at 2:10 p.m. and 2:44 p.m.

"0 1510?* MON-FRI" Triggers from Monday to Friday at 10:15 a.m.

"0 15 10 15 *?" Triggered at 10:15 a.m. on the 15th of each month

"0 15 10 L *?" Triggered at 10:15 on the last day of each month

"0 1510?* 6L" Triggers at 10:15 a.m. on the last Friday of the month

"0 1510?* 6L 2002-2005" Triggered at 10:15 a.m. on the last Friday of each month, 2002-2005

"0 1510?* 6#3" Triggers on the third Friday of the month at 10:15 a.m.

Some subexpressions can contain ranges or lists

For example, the subexpression (day (week)) can be "MON-FRI", "MON, WED, FRI", "MON-WED,SAT"

The'*'character represents all possible values
The'/'character specifies the increment of the value

For example, "0/15" in a subexpression (minutes) means that every 15 minutes, starting at the 0th minute
"3/20" in the subexpression (minutes) means every 20 minutes, starting at the third minute (it has the same meaning as "3, 23, 43")

"?"Characters are only used in day (month) and day (week) subexpressions to indicate that no value is specified
When one of the two subexpressions is assigned a value, you need to set the value of the other subexpression to'?'in order to avoid conflicts.

The "L" character is used only in day (month) and day (week) subexpressions and is an abbreviation for the word "last"
If there is something specific before L, it has other meanings.

For example, "6L" means the last sixth day of the month
Note: When using the L parameter, do not specify a list or range, as this can cause problems

The W character represents weekdays (Mon-Fri) and can only be used in the solar field.It is used to specify the nearest weekday from a specified day.Most business processes are based on work week, so the W character may be important.

For example, 15W in the solar field means "the closest weekday to the 15th of the month."If the 15th is Saturday, the trigger will be triggered on the 14th (Friday), because Thursday is closer to the 15th than Monday.

C: stands for Calendar.It means that the dates associated with the plan, if not associated, correspond to all dates in the calendar.

For example, 5C in the date field is equivalent to the first day after the fifth day of the calendar.1C in the week field corresponds to the first day after the week.

Integrate Quartz

===========

Add Dependency

If the SpringBoot version is after 2.0.0, the quart dependency is already included in the spring-boot-starter, you can use the spring-boot-starter-quartz dependency directly:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

If it is 1.5.9, use the following to add dependencies:

<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.3.0</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
</dependency>

Here I use SpringBoot version 2.0.0.BUILD-SNAPSHOT, which started integrating Quartz, so it's easy to see.Others seem cumbersome, so don't mention them here. You'll have time to learn more about Quartz later.

Create a task class, TestQuartz, that inherits mainly QuartzJobBean

public class TestQuartz extends QuartzJobBean {

    /**
     * Perform timed tasks
     * @param jobExecutionContext
     * @throws JobExecutionException
     */

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        System.out.println("quartz task "+new Date());

    }

}

Create Configuration Class QuartzConfig

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail teatQuartzDetail(){

        return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();

    }

    @Bean
    public Trigger testQuartzTrigger(){

        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)  //Set time cycle unit seconds
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())

                .withIdentity("testQuartz")
                .withSchedule(scheduleBuilder)
                .build();

    }

}

Start Project

These are all simple descriptions of how SpringBoot timer tasks are handled. It should be most convenient to use the SpringTask annotations directly, while using Quartz from 2.0 is also very convenient.There are advantages to each of these two approaches, so choose what you need.Additionally, detailed information about Quartz can be found in the official documentation

Focus on the Java technology stack WeChat Public Number and reply back to the keyword: boot, you can get more stack-length sorted Spring Boot series technology dry goods.

Recommend going to my blog to read more:

1.Java JVM, Collections, Multithreaded, New Features Series Tutorial

2.Spring MVC, Spring Boot, Spring Cloud series tutorials

3.Maven, Git, Eclipse, Intellij IDEA Series Tools Tutorial

4.Latest Interview Questions for Java, Backend, Architecture, Alibaba, etc.

Feel good, don't forget to say yes + forward!

Topics: Java Spring SpringBoot less