一、背景

在工作中,有些时候我们有些定时任务的执行可能是需要动态修改的,比如: 生成报表,有些项目配置每天的8点生成,有些项目配置每天的10点生成,像这种动态的任务执行时间,在不考虑分布式执行的情况下,我们可以
使用 spring task来简单的实现。

二、需求和实现思路

1、能够动态的添加一个定时任务。

spring中存在一个类threadpooltaskscheduler,它可以实现根据一个cron表达式来调度一个任务,并返回一个scheduledfuture对象。

2、能够取消定时任务的执行。

通过调用上一步的scheduledfuturecancel方法,就可以将这个任务取消。

3、动态的修改任务执行的时间。

先取消任务。然后在重新注册一个任务。

4、获取定时任务执行的异常

threadpooltaskscheduler类中有一个设置errorhandler的方法,给自己实现的errorhandler即可。

提示:

  1. spring中我们通过@scheduled注解来实现的定时任务,底层也是通过threadpooltaskscheduler来实现的。可以通过scheduledannotationbeanpostprocessor类来查看。
  2. threadpooltaskscheduler的默认线程数是1,这个需要根据实际的情况进行修改。

三、代码实现

此处只给出动态注册定时任务和取消的定时任务的代码。

package com.huan.study.task.jobs.tasks;

import lombok.extern.slf4j.slf4j;
import org.springframework.beans.factory.initializingbean;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.scheduling.concurrent.threadpooltaskscheduler;
import org.springframework.scheduling.support.cronexpression;
import org.springframework.scheduling.support.crontrigger;
import org.springframework.stereotype.component;

import java.time.localdatetime;
import java.time.format.datetimeformatter;
import java.util.concurrent.scheduledfuture;
import java.util.concurrent.timeunit;

/**
 * @author huan.fu 2021/7/8 - 下午2:46
 */
@component
@slf4j
public class dynamiccrontask implements initializingbean {

    @autowired
    private threadpooltaskscheduler taskscheduler;


    private scheduledfuture<?> scheduledfuture;

    @override
    public void afterpropertiesset() throws exception {
        // 动态启动一个定时任务
        log.info("注册一个定时任务:每隔1秒执行一次");
        scheduledfuture = register("* * * * * ?");

        // 取消一个调度
        new thread(() -> {
            try {
                timeunit.seconds.sleep(5);
                log.info("取消调度");
                scheduledfuture.cancel(false);
                log.info("取消结果:" + scheduledfuture.iscancelled());
                log.info("重新注册一个定时任务:每隔2秒执行一次");
                register("*/2 * * * * ?");
            } catch (interruptedexception e) {
                e.printstacktrace();
            }
        }).start();
    }

    private scheduledfuture<?> register(string cron) {

        // 高版本使用 cronexpression,低版本使用 cronsequencegenerator
        boolean validexpression = cronexpression.isvalidexpression(cron);
        log.info("cron:[{}]是合法的吗:[{}]", cron, validexpression);

        cronexpression expression = cronexpression.parse(cron);
        localdatetime nextexectime = expression.next(localdatetime.now());
        if (null != nextexectime) {
            log.info("定时任务下次执行的时间为:[{}]", nextexectime.format(datetimeformatter.ofpattern("yyyy-mm-dd hh:mm:ss")));
        }

        return taskscheduler.schedule(new runnable() {
            @override
            public void run() {
                log.info("我执行了");
            }
        }, new crontrigger(cron));
    }
}

四、执行结果

五、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-task

到此这篇关于spring动态添加定时任务的实现思路的文章就介绍到这了,更多相关spring定时任务内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!