First, what is a scheduled task

Timed tasks are often used in development, and as the name implies, timed tasks are timed execution methods, i.e., timed code. To reduce the burden on the server or database, for example, we will put some on A server or database, such as high frequency operation pressure, timing to perform instead, such as every night at 0 am synchronization system, A system of data to B statistical user integral situation, every 2 hours A week to pay treasure to users to push revenue expenditure data report last week, etc. Generally, many services are processed in the early hours of the morning to avoid peak user hours and have sufficient server resources with little impact on users.

As an excellent framework, SpringBoot naturally provides us with scheduled tasks, which can be used in three ways. The first is the use of annotations (common), which cannot dynamically change the time of scheduled tasks. The second is to dynamically change the time of scheduled tasks; The third type is the scheduled task that can be manually started, stopped, and changed.

2. Project dependence

Since SpringBoot provides timed tasks, we first need to introduce SpringBoot-related dependencies, and since the demo uses interface calls, we also introduce Web-related dependencies. The demo project then uses the Maven project and ultimately relies on POM.xml as follows:


      
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10. RELEASE</version>
        <relativePath/> <! -- lookup parent from repository -->
    </parent>
    <groupId>com.nobody</groupId>
    <artifactId>scheduled-task</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
    <name>scheduled-task</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
Copy the code

Annotated scheduled tasks

This is as simple as annotating @scheduled on methods that need to be executed regularly. The following indicates that the test method is executed at 00:00 every day.

@Scheduled(cron = "0 0 0 * * ? ")
public void test(a) {
    // doSomething
}
Copy the code

The @Scheduled annotation has several properties, and we’ll explain what it does.

package org.springframework.scheduling.annotation;

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

	String CRON_DISABLED = "-";

	String cron(a) default "";

	String zone(a) default "";

	long fixedDelay(a) default- 1;

	String fixedDelayString(a) default "";

	long fixedRate(a) default- 1;

	String fixedRateString(a) default "";

	long initialDelay(a) default- 1;

	String initialDelayString(a) default "";
}
Copy the code

3.1 the cron

String CRON_DISABLED = "-";
String cron(a) default "";
Copy the code

Its value is a CRon expression string that specifies when a scheduled task is executed. If its value is a special “-” string, as defined by the CRON_DISABLED attribute, the scheduled task is invalid and will not be executed. This special value is primarily used for externally specified values, namely the placeholder ${… }, you can flexibly enable or disable scheduled tasks using the configuration file.

This approach is the most common, and cron’s power allows us to cover a wide range of time configurations.

I won’t go into the details of cron expressions, but here is a recommended site for generating crons:cron.qqe2.com/ Note that the easiest way to assign the class of the scheduled task to the Spring container is to add the @Component annotation to the class, as follows:

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/ * * *@DescriptionScheduled task *@Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class ScheduledTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);
	// Execute every 5 seconds
    @Scheduled(cron = "0/5 * * * * ? ")
    public void test(a) {
        LOGGER.info(">>> ScheduledTask test... "); }}Copy the code

And it must be activated via @enablescheduling annotation, otherwise it won’t work.

package com.nobody;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class ScheduledTaskApplication {
    public static void main(String[] args) { SpringApplication.run(ScheduledTaskApplication.class, args); }}Copy the code

We started the service and could see the scheduled task executed every 5 seconds in the control.

23:44:00 2021-03-02. 10852-005 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 23:44:05 2021-03-02. 10852-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 23:44:10 2021-03-02. 10852-000 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 23:44:15 2021-03-02. 10852-002 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 23:44:20 2021-03-02. 10852-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest.Copy the code

The value of cron can be specified in an external configuration file as follows:

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/ * * *@DescriptionScheduled task *@Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class ScheduledTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);
	// Execute every 5 seconds
    @Scheduled(cron = "${cron.exp}")
    public void test(a) {
        LOGGER.info(">>> ScheduledTask test... "); }}Copy the code

Then fill in the value of the configuration variable in the configuration file application.properties, which is flexible and allows you to change the time without modifying the code. If the value is changed to “-“, the scheduled task is invalid.

cron.exp=0/5 * * * * ? 
#cron.exp=-
Copy the code

3.2 fixedDelay

long fixedDelay(a) default- 1;
Copy the code

This attribute indicates how long the scheduled task will be executed again after the last scheduled task is executed. In milliseconds.

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/ * * *@DescriptionScheduled task *@Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class ScheduledTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);
    // Delay 1 second
	@Scheduled(fixedDelay = 1000)
    public void test(a) {
        try {
            // Sleep for 2 seconds
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info(">>> ScheduledTask test... "); }}Copy the code

The output is as follows, exactly 3 seconds apart (2 seconds sleep +1 second delay).

00:03:44 2021-03-03. 15612-025 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:03:47 2021-03-03. 15612-027 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:03:50 2021-03-03. 15612-029 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:03:53 2021-03-03. 15612-031 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest.Copy the code

3.3 fixedDelayString

String fixedDelayString(a) default ""
Copy the code

This attribute indicates how long the scheduled task will be executed again after the last scheduled task is executed. In milliseconds. Same as fixedDelay, except that the value is a string. But it does support placeholders.

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/ * * *@DescriptionScheduled task *@Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class ScheduledTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);
    // Delay 1 second
	@Scheduled(fixedDelayString = "1000")
    public void test(a) {
        try {
            // Sleep for 2 seconds
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info(">>> ScheduledTask test... "); }}Copy the code

The output is as follows, exactly 3 seconds apart (2 seconds sleep +1 second delay).

00:09:58 2021-03-03. 9644-234 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:10:01 2021-03-03. 9644-238 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:10:04 2021-03-03. 9644-262 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:10:07 2021-03-03. 9644-340 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest.Copy the code

Use placeholders as shown below, and specify the value of the configuration variable in the configuration file application.properties.

@Scheduled(fixedDelayString = "${fixed.delay}")
Copy the code
fixed.delay=1000
Copy the code

3.4 fixedRate

long fixedRate(a) default- 1;
Copy the code

This property indicates the number of milliseconds between scheduled task invocations. That is, the delay in calling again after the last call has started (without waiting for the last call to complete).

But by default, a single thread is used to perform all scheduled tasks, so even if the previous call has not finished and the next call has started, it must wait for the next call to finish before it can execute the next one.

@Scheduled(fixedRate = 1000)
public void test(a) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    LOGGER.info(">>> ScheduledTask test... ");
}
Copy the code

The two scheduled task invocations are 1 second apart and execute in 5 seconds, but they execute in 5 seconds apart and print the same thread name taskScheduler-1, which proves that this is true by default.

00:20:35 2021-03-03. 16152-307 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:20:40 2021-03-03. 16152-309 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:20:45 2021-03-03. 16152-309 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:20:50 2021-03-03. 16152-310 the INFO [] TaskScheduler - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest.Copy the code

However, we can customize the thread pool and then use the custom thread pool to execute asynchronously via the @async annotation to achieve multi-threaded execution. However, if a scheduled task performs the same service operations, such as calculating user credits, concurrent operations may occur. Therefore, this task is not recommended. However, if the execution time is less than the interval between two schedules, it can be considered.

@Scheduled(fixedRate = 1000)
@Async("myExecutor")
public void test(a) {
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    LOGGER.info(">>> ScheduledTask test... ");
}
Copy the code

The thread pool configuration class code is as follows:

package com.nobody.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class ExecutorConfig {

    public static final int CORE_POOL_SIZE = 5;
    public static final int MAX_POOL_SIZE = 15;
    public static final int QUEUE_CAPACITY = 100;

    @Bean("myExecutor")
    public Executor asyncServiceExecutor(a) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // The number of core threads
        executor.setCorePoolSize(CORE_POOL_SIZE);
        // Maximum number of threads
        executor.setMaxPoolSize(MAX_POOL_SIZE);
        // Block queue capacity
        executor.setQueueCapacity(QUEUE_CAPACITY);
        // Thread name prefix
        executor.setThreadNamePrefix("myTask-");
        // rejectionPolicy: Processing policy for new tasks when queue reaches maxSize and maxPoolSize reaches its maximum value
        // CallerRunsPolicy: The task is not executed in the new thread, but in the caller's thread
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        returnexecutor; }}Copy the code

You need to add the @enableAsync annotation activation.

package com.nobody;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class ScheduledTaskApplication {

    public static void main(String[] args) { SpringApplication.run(ScheduledTaskApplication.class, args); }}Copy the code

The final output shows that the interval is 1 second instead of 5 seconds, and instead of a single thread executing the scheduled task, it is executed through the configured thread pool.

00:36:41 2021-03-03. 5752-010 the INFO [] myTask - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 00:36:41 2021-03-03. 5752-993 the INFO [myTask - 2] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:42. 5752-998 the INFO [myTask - 3] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:43. 5752-991 the INFO [myTask - 4] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:44. 5752-993 the INFO [myTask - 5] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:36:46 2021-03-03. 5752-013 the INFO [] myTask - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 00:36:47 2021-03-03. 5752-023 the INFO [myTask - 2] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:47. 5752-999 the INFO [myTask - 3] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:48. 5752-992 the INFO [myTask - 4] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 2021-03-03 00:36:50. 5752-020 the INFO [myTask - 5] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. 00:36:51 2021-03-03. 5752-013 the INFO [] myTask - 1 com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest. The 00:36:52 2021-03-03. 5752-025 the INFO [myTask - 2] com. Nobody. Task. ScheduledTask: > > > ScheduledTasktest.Copy the code

3.5 fixedRateString

String fixedRateString(a) default "";
Copy the code

This property indicates the number of milliseconds between scheduled task invocations. That is, the delay in calling again after the last call has started (without waiting for the last call to complete). Same as fixedRate, except the value is a string. But it does support placeholders.

3.6 initialDelay and initialDelayString

long initialDelay(a) default- 1;
Copy the code

InitialDelay This property indicates the number of milliseconds to delay before the first execution of a fixedRate or fixedDelay task. This parameter is used with fixedDelay or fixedRate. InitialDelayString is a string and supports placeholders.

// Start the first task with a delay of 3 seconds
@Scheduled(fixedDelayString = "1000", initialDelay = 3000)
public void test(a) {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    LOGGER.info(">>> ScheduledTask test... ");
}
Copy the code

3.7 zone

String zone(a) default "";
Copy the code

Time zone, based on which the CRon expression is resolved. The default is an empty string that takes the time zone where the server is located. The value is a time zone ID, and the time zone we normally use is Asia/Shanghai. This property is generally the default.

@Scheduled(cron = "0/5 * * * * ?" , zone = "Asia/Shanghai")
public void test(a) {
    TimeZone defaultTimeZone = TimeZone.getDefault();
    LOGGER.info(">>> ScheduledTask test... " + defaultTimeZone.getID());
    // Prints out all available time zone ids
    String[] availableIDs = TimeZone.getAvailableIDs();
    System.out.println(Arrays.toString(availableIDs));
    try {
        Thread.sleep(2000);
    } catch(InterruptedException e) { e.printStackTrace(); }}Copy the code

4. A scheduled task whose time can be changed

This approach implements the SchedulingConfigurer interface and overrides the configureTasks method.

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

/ * * *@DescriptionA scheduled task whose time can change dynamically@Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class ChangeTimeScheduledTask implements SchedulingConfigurer {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChangeTimeScheduledTask.class);

    // Cron expression, we can dynamically change the value of this property to change the execution time of scheduled tasks
    private String expression = "0/5 * * * * *";

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        // The method to execute the scheduled task
        Runnable task = () -> LOGGER.info(">>> configureTasks ...");
        // Scheduling implements time control
        Trigger trigger = triggerContext -> {
            CronTrigger cronTrigger = new CronTrigger(expression);
            return cronTrigger.nextExecutionTime(triggerContext);
        };
        taskRegistrar.addTriggerTask(task, trigger);
    }

    public String getExpression(a) {
        return expression;
    }

    public void setExpression(String expression) {
        this.expression = expression; }}Copy the code

We then write an interface to call to dynamically change the timing of the scheduled task.

package com.nobody.controller;

import com.nobody.task.ChangeTimeScheduledTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/ * * *@Description
 * @Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@RestController
@RequestMapping("demo")
public class DemoController {

    private ChangeTimeScheduledTask changeTimeScheduledTask;

    public DemoController(final ChangeTimeScheduledTask changeTimeScheduledTask) {
        this.changeTimeScheduledTask = changeTimeScheduledTask;
    }

    @GetMapping
    public String testChangeTimeScheduledTask(a) {
        changeTimeScheduledTask.setExpression("0/10 * * * * *");
        return "ok"; }}Copy the code

Scheduled tasks are executed every 5 seconds before the service is started and the interface is called.

The 13:56:20 2021-03-03. 6836-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: >>> configureTasks ... The 13:56:25 2021-03-03. 6836-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: >>> configureTasks ... The 13:56:30 2021-03-03. 6836-002 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: >>> configureTasks ... 13:56:35 2021-03-03. 6836-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: > > > configureTasks...Copy the code

We then call the interface and change the timing of the scheduled task to one every 10 seconds.

The 13:56:40 2021-03-03. 6836-005 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: >>> configureTasks ... The 13:56:50 2021-03-03. 6836-002 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: >>> configureTasks ... 13:57:00 2021-03-03. 6836-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. ChangeTimeScheduledTask: > > > configureTasks...Copy the code

5. You can start, stop, and change scheduled tasks

In this mode, you can manually start or stop scheduled tasks, and change the execution time of scheduled tasks.

Its principle is to use the thread pool to realize the task scheduling, which can realize the task scheduling and deletion. With the ThreadPoolTaskScheduler, thread pools can be enabled for task scheduling. A schedule Future is created using the Schedule method of ThreadPoolTaskScheduler, which has a cancel method to stop the scheduled task. The schedule method has two parameters, one is the Runnable task, the thread interface class, which is the method we want to execute on a regular basis, and the other parameter is Trigger Trigger, which is the scheduled task Trigger, which has a cron value.

package com.nobody.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.concurrent.ScheduledFuture;

/ * * *@Description
 * @Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Component
public class DynamicScheduledTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(DynamicScheduledTask.class);

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    public DynamicScheduledTask(final ThreadPoolTaskScheduler threadPoolTaskScheduler) {
        this.threadPoolTaskScheduler = threadPoolTaskScheduler;
    }

    private ScheduledFuture future;

    /** * Start timer */
    public void startTask(a) {
        // The first parameter is the method to execute the scheduled task, and the second parameter is the time to execute the scheduled task
        future = threadPoolTaskScheduler.schedule(this::test, new CronTrigger("0/5 * * * * *"));
    }

    /** * Stop the timer */
    public void endTask(a) {
        if(future ! =null) {
            future.cancel(true); }}/** * To change the scheduling time, stop the timer before starting a new timer */
    public void changeTask(a) {
        // Stop the timer
        endTask();
        // Define a new execution time and start
        future = threadPoolTaskScheduler.schedule(this::test, new CronTrigger("0/10 * * * * *"));
    }

    /** * The method for executing scheduled tasks */
    public void test(a) {
        LOGGER.info(">>> DynamicScheduledTask ..."); }}Copy the code

We need to create an instance of ThreadPoolTaskScheduler and hand it over to the Spring container to manage.

package com.nobody.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

/ * * *@Description
 * @Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@Configuration
public class ThreadPoolTaskSchedulerConfig {
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(a) {
        return newThreadPoolTaskScheduler(); }}Copy the code

Finally write interface, start, stop, change time can be called.

package com.nobody.controller;

import com.nobody.task.DynamicScheduledTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/ * * *@Description
 * @Author Mr.nobody
 * @Date 2021/3/2
 * @Version1.0.0 * /
@RestController
@RequestMapping("demo")
public class DemoController {

    private DynamicScheduledTask dynamicScheduledTask;

    public DemoController(final DynamicScheduledTask dynamicScheduledTask) {
        this.dynamicScheduledTask = dynamicScheduledTask;
    }

    @GetMapping("startDynamicScheduledTask")
    public String startDynamicScheduledTask(a) {
        dynamicScheduledTask.startTask();
        return "ok";
    }

    @GetMapping("endDynamicScheduledTask")
    public String endDynamicScheduledTask(a) {
        dynamicScheduledTask.endTask();
        return "ok";
    }

    @GetMapping("changeDynamicScheduledTask")
    public String changeDynamicScheduledTask(a) {
        dynamicScheduledTask.changeTask();
        return "ok"; }}Copy the code

Start the service, because the start timer interface is not called, the scheduled task will not execute. Scheduled tasks can be executed only after the started interface is invoked. When the service is running, you can start, stop, and change the time of scheduled tasks.

The 14:11:35 2021-03-03. 8548-000 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:11:40 2021-03-03. 8548-002 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:11:45 2021-03-03. 8548-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:11:50 2021-03-03. 8548-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:11:55 2021-03-03. 8548-002 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... / / the following is to change the execution time for 10 seconds 2021-03-03 14:12:00. 8548-001 the INFO] [TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:12:10 2021-03-03. 8548-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ... The 14:12:20 2021-03-03. 8548-001 the INFO [] TaskScheduler - 1 com. Nobody. Task. DynamicScheduledTask: >>> DynamicScheduledTask ...Copy the code

Six, distributed cluster precautions

Although Scheduled Task is a lightweight Task scheduler, it has much less configuration information than Quartz. One drawback of Scheduled Tasks is that they do not work well with distributed clusters because the cluster nodes do not share Task information, resulting in repeated Scheduled tasks being executed on multiple servers.

If the same scheduled tasks are performed on multiple servers, your business is fine. However, some services are not allowed to repeat execution, so we can actually use a distributed lock, and only one of the nodes with the lock to perform the scheduled task.

@Scheduled(cron = "${cron.exp}")
public void test(a) {
    String lockKey = RedisKeyUtil.genKey(RedisKeyUtil.SCHEDULED_TASK_LOCK);
    boolean lockSuccess = redisUtils.getLock(lockKey, "1".30000);
    if(! lockSuccess) { LOGGER.warn(">>> Scheduled is running on another server...");
        return;
    }
    try {
        // doSomething();
    } finally {
        redisUtils.releaseLock(lockKey, "1"); }}Copy the code

This demo project has been uploaded to Github, if you need to download, welcome Star. Github.com/LucioChn/sp…

Welcome to wechat public account: “Java words” technical articles continue to update, please continue to follow……

  • Learn the latest technical articles as soon as possible
  • Get the latest technology learning materials video
  • Latest Internet information and interview experience