preface

  • Traditional timers are hard-coded. But sometimes the business needs to be constantly tweaked

Problem description

  • We developed a function to set the alarm clock. This feature must be timer development. But there’s a problem with that because the timing is dynamic. So how do we do that? Spring Boot Core learning Notes sharing.

Introduction to the

  • Timers are a real boon in development. We save a lot of manpower by using timers. We use timers to complete some tedious regular things through code. In Java development, we can simply realize the Timer function through the Timer class. Since it’s Springboot today we’re going to look at srPingboot integration timers

Conventional timer

  • This is the configuration from lesson 1. Springboot is intended to be a series of tutorials. So the configuration is connected to the past. I suggest you watch it in order.
@Component
public class SimpleSchedule {

    @Autowired
    TestMapper testMapper;

    @Scheduled(cron = "*/6 * * * *?")
    private void process(){ List<test> tests = testMapper.getTests(); System.out.println(tests); }}Copy the code
  • Timers are also easy to write with the @scheduled annotation on a class or method. Then you can configure the CRon expression. Note here that you need to annotate the development timer on the SpirngBoot startup class.
@SpringBootApplication
public class CrontabApplication {
    public static void main(String[] args){ SpringApplication.run(CrontabApplication.class, args); }}Copy the code

  • In the code, we use the simplest approach.
  • Cron expression: Specifies that the task is executed at a specific time
  • FixedDelay: indicates the time after the last task is executed. Parameter type: long, unit: ms
  • FixedDelayString: Same as fixedDelay except that the parameter type is String
  • FixedRate: Indicates that tasks are executed at a certain frequency. Parameter Type Long, unit: ms For example, fixedRate(5000) : indicates that tasks are executed every five seconds
  • FixedRateString: Same as fixedRate, except that the parameter type is changed to String
  • InitialDelay: indicates the delay for executing the task for the first time. The parameter type is long and the unit is ms
  • InitialDelayString: The same as initialDelay, but the parameter type is String

Dynamic timer

  • The above timer has been successfully configured. But now there is a requirement that the customer wants to customize the frequency of the timer execution through the page. The above code we are to write 6S execution once. If the customer wants to configure through visualization. I can’t rewrite the code manually after I’ve configured it. Then dynamic timers are born.

V1.0

  • Since it’s dynamic we have to localize the customer configuration data. Stored in a database, of course.

  • Corresponding to the newly created Mapper to query scheduled task information. Because only expressions are configured here. No timer is configured for the expression. It’s also for testing. Here the default expression is one.
@Configuration
public class ScheduleConfigV1 implements SchedulingConfigurer {

    @Autowired
    CronMapper cronMapper;
    @Autowired
    TestMapper testMapper;
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(()-> {
                    System.out.println("Execute timer task :" + LocalDateTime.now().toLocalTime());
                    List<test> tests = testMapper.getTests();
                    System.out.println(tests);
                },
                triggerContext -> {
                    List<cron> crons = cronMapper.getCron();
                    Cron cron = crons.get(0);
                    return newCronTrigger(cron.getCron()).nextExecutionTime(triggerContext); }); }}Copy the code
  • To execute this code we’d better turn off the previous static timer. This is a little bit more obvious. First, the database is configured to execute every 6 seconds. Then change the data to execute every 2 seconds. Look at the effect.

  • We found that as soon as the database information was changed. The frequency of scheduled tasks is automatically changed. Most importantly, we don’t need to restart our code.
  • It’s dynamically configured. But there is a drawback. The modification takes effect after the next trigger timer is executed. In plain English, it is executed once an hour at the beginning, and changes made during this time do not take effect immediately until the next one hour to refresh the configuration. The dynamics here can be understood as lazy dynamics.

V2.0

  • The above functionality is dynamic though. But it’s definitely not scientific for mass production. First of all, you can’t just store one piece of data in a database.
  • If there are multiple data stores, how can multiple timing rules be matched with specific timers?
  • Since it is dynamic then how to control the timer through the database switch?
  • Scheduler.schedule (task, new CronTrigger(“*/2 * * * *?” )); The implementation. The object returned by this method is ScheduledFuture. Cancels scheduled tasks using the canel method. Based on these two methods, let’s improve our previous timed task.

Registar

  • First we provide a registry whose function is to manage scheduled tasks. Add and delete functions. Scheduler.schedule (task, new CronTrigger(“*/2 * * * *?” )); To start a scheduled task. The previously obtained ScheduledFuture is called on the delete node to canel the scheduled task. The advantage of this is that we can control the timing of the task on and off at any time
public void addCronTask(Runnable task, String cron) {
    addCronTask(new CronTask(task,cron));
}
Copy the code
  • The above addition requires a runnable and cron expression. Use a ConcurrentHashMap to manage the added runnable. Runnable is the key and ScheduledTask is the value.
public ScheduledTask scheduleCronTask(CronTask cronTask) {
    ScheduledTask scheduledTask;
    scheduledTask = new ScheduledTask();
    scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());
    return scheduledTask;
  }
Copy the code
  • This builds a ScheduledTask object.
public final class ScheduledTask { public volatile ScheduledFuture<! -? --> future;/** * Cancel the scheduled task */
    public void cancel(){ ScheduledFuture<! -? --> future =this.future;
        if(future ! =null) {
            future.cancel(true); }}}Copy the code
  • This allows us to start the thread by building a runnable thread and registering it with the registry with expressions that have been executed at a fixed frequency. Close the thread with remove.
SchedulingRunnable task = new SchedulingRunnable(TestMapper.class, "getTests".null);
cronTaskRegistrar.addCronTask(task, "0/10 * * * *?"); Spring Boot learning notes + interview question 【 attach answer analysis sharing 】Copy the code
  • The advantage of this is that we can update the timed task rules immediately if the table data changes.

conclusion

– The above code has been uploaded to gitee address: gitee.com/zxhTom/cron…

  • The following Java classes are the ones we will use this time.
  • SchedulingConfigurer
  • DisposableBean
  • ConcurrentHashMap