Spring Boot 任务调度

2.1.12 定时任务

Spring 框架自带任务调度功能,比如一个轻量级的Quartz,使用简单、方便,不须要依赖其余JAR包。java

只须要在项目主程序启动类上添加@EnableScheduling开启任务调度功能便可数据库

@SpringBootApplication
@EnableScheduling
public class LearnApplication {
    public static void main(String[] args) {
        SpringApplication.run(LearnApplication.class, args);
    }
}
2.1.12.1 简单定时任务
@Component
public class TestTask {

    @Scheduled(cron = "0/10 * * * * *")
    public void testTask1() {
        System.out.println("【任务一】测试定时任务" + LocalDateTime.now());
    }

}

如上述,配置一个简单的定时任务只须要在调度方法上添加@Shceduled注解便可,就可使用定时任务。markdown

2.1.12.2 异步定时任务
@Component
// 开启异步支持
@EnableAsync
public class TestTask {

    @Scheduled(cron = "0/10 * * * * *")
    // 方法使用异步执行,每次任务建立一个线程执行任务
    @Async
    public void testTask1() {
        System.out.println("【任务一】测试定时任务" + LocalDateTime.now() + "   " + Thread.currentThread().getName());
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("【任务一】休眠" + (i + 1) + "秒测试定时任务" + LocalDateTime.now() + "   " + Thread.currentThread().getName());
        }

    }

}

每每在咱们的项目调度任务中,有的场景是须要在当前任务尚未执行完毕时,就须要执行下一个定时调度任务,在这种状况下须要使用异步的方式来执行定时任务。框架

@EnableAsync开启异步支持异步

@Async标记任务使用异步执行(下次任务将在下一个配置时间开始,不等待当前任务执行完毕)ide

2.1.12.3 动态定时任务

当咱们编写定时任务是,流程大体为:编码->配置执行周期->启动服务。测试

当前咱们配置的执行周期是天天早上8点执行,当咱们有天,需求变动,须要天天晚上8点执行,咱们的操做流程为:修改执行周期->新版打包->停服->启动新版服务。整个流程线步骤多,存在不可控因素。编码

那么咱们怎么作到不停服更新咱们的执行周期呢??线程

那么下面咱们模拟将cron表达式存储在MySQL。日志

1)定义cron相关service

// 表达式相关接口
public interface SwitchService {

    /**
     * 获取最新 cron 表达式
     *
     * @param taskId 任务ID
     * @return 最新 cron表达式
     */
    String getCron(String taskId);

    /**
     * 修改 cron 表达式
     */
    void modify();

}
// 表达式相关接口实现
@Service
public class SwitchServiceImpl implements SwitchService {

    private static String DB_CRON = "";

    @Override
    public String getCron(String taskId) {
        System.out.println("执行数据库查询 DB_CRON " + LocalDateTime.now());
        return DB_CRON;
    }

    @Override
    public void modify() {
        DB_CRON = "0/20 * * * * *";
        System.out.println("修改数据库中 DB_CRON " + LocalDateTime.now());
    }
}

此处模拟修改以及查询

2)建立具体任务执行

@Component
public class DynamicCronTask implements SchedulingConfigurer {
    // 模拟当前任务ID
    private String TASK_ID = "5001";

    @Autowired
    private SwitchService switchService;

    private String SpringDynamicCronTask() {
        // 默认为 每5秒执行
        String cron = "0/5 * * * * ?";
        //从数据库得到配置的corn表达式
        String dbCron = switchService.getCron(TASK_ID);
        // 当查询为空时,使用默认的表达式
        if (StringUtils.isNotBlank(dbCron)) {
            return dbCron;
        }
        return cron;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                // 任务逻辑
                System.out.println("执行任务逻辑...." + LocalDateTime.now());
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                String s = SpringDynamicCronTask();
                // 任务触发,可修改任务的执行周期
                CronTrigger trigger = new CronTrigger(s);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        });
    }

}

3)启动服务

查看执行日志

执行数据库查询 DB_CRON 2020-06-09T10:33:30.001
执行任务逻辑....2020-06-09T10:33:35.002
执行数据库查询 DB_CRON 2020-06-09T10:33:35.002
执行任务逻辑....2020-06-09T10:33:40.001
执行数据库查询 DB_CRON 2020-06-09T10:33:40.001

修改数据库中 DB_CRON 2020-06-09T10:33:42.085

执行任务逻辑....2020-06-09T10:33:45
执行数据库查询 DB_CRON 2020-06-09T10:33:45

执行任务逻辑....2020-06-09T10:34:00.001
执行数据库查询 DB_CRON 2020-06-09T10:34:00.001
执行任务逻辑....2020-06-09T10:34:20.002
执行数据库查询 DB_CRON 2020-06-09T10:34:20.002

经过日志能够看出,在应用启动时,会首先从数据库中查询配置的执行周期,而后执行定时任务,执行完毕后会再次查询执行周期,下一个执行时间结束后就会按照修改的执行时间执行。

生效时间为下一个执行时间结束后,作不到当即生效!!!

相关文章
相关标签/搜索