Spring中的Schedule动态添加修改定时任务详解

 更新时间:2023年11月06日 11:23:09   作者:杨某人信了你的邪  
这篇文章主要介绍了Spring中的Schedule动态添加修改定时任务详解,可能有人会问,为啥不用Quartz,Quartz自然是非常方便强大的,但不是本篇要讲的内容,本篇就偏要使用SpringSchedule来实现动态的cron表达式任务,需要的朋友可以参考下

Spring Schedule如何动态添加修改定时任务

1、快速开始

通常情况下,我们使用的功能很简单,只需要在配置类上加一个@EnableScheduling注解,然后在Bean对应的方法上添加@Scheduled注解即可。但一般情况下,还会自定义对应的线程池等信息,如下所示。

@EnableScheduling
@Configuration
public class SchedulerConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = threadPoolTaskScheduler();
        taskRegistrar.setScheduler(taskScheduler);
    }

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(Runtime.getRuntime().availableProcessors() / 3 + 1);
        scheduler.setThreadNamePrefix("scheduler-");
        scheduler.setRemoveOnCancelPolicy(true);
        return scheduler;
    }
}

@Scheduled注解通常有三种调度方式,fixedRate、fixedDelay和cron。

  • fixedRate:定时执行,如@Scheduled(fixedRate= 2000)会每隔两秒执行一次
  • fixedDelay:固定延迟,如@Scheduled(fixedDelay= 2000)会在上次任务执行完成后,延迟两秒再触发下一次
  • cron:自定义规则,比较复杂,功能更强大

2、Schedule的动态修改

以cron表达式任务为例,在上面的基础上,如果有如下定时任务,在每天凌晨一点执行一次,但是后面发现时间不合适,需要修改触发时间为凌晨两点,按照现有的方式,通常只能修改代码重新部署了。

@Scheduled(cron = "0 0 1 * * ?")
public void foo() {
    // do something
}

可能有人会问,为啥不用Quartz?Quartz自然是非常方便强大的,但不是本篇要讲的内容,本篇就偏要使用SpringSchedule来实现动态的cron表达式任务。

在上面的快速开始一节中,通过configureTasks,我们可以拿到ScheduledTaskRegistrar实例,在这个实例中提供了很多的操作定时任务方法

public ScheduledTask scheduleTriggerTask(TriggerTask task) {/**/}
public ScheduledTask scheduleCronTask(CronTask task) {/**/}
public ScheduledTask scheduleFixedRateTask(IntervalTask task) {/**/} 
public ScheduledTask scheduleFixedRateTask(FixedRateTask task) {/**/}
public ScheduledTask scheduleFixedDelayTask(IntervalTask task) {/**/}
public ScheduledTask scheduleFixedDelayTask(FixedDelayTask task) {/**/}

修改第一步中的配置如下,为了操作简单,这里直接通过ApplicationRunner来进行测试

@Slf4j
@EnableScheduling
@Configuration
public class SchedulerConfig implements SchedulingConfigurer, ApplicationRunner {

    private ScheduledTaskRegistrar taskRegistrar;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        ThreadPoolTaskScheduler taskScheduler = threadPoolTaskScheduler();
        taskRegistrar.setScheduler(taskScheduler);

        this.taskRegistrar = taskRegistrar;
    }

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(Runtime.getRuntime().availableProcessors() / 3 + 1);
        scheduler.setThreadNamePrefix("scheduler-");
        scheduler.setRemoveOnCancelPolicy(true);
        return scheduler;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        CronTask cronTask = new CronTask(() -> log.info("foo-----------"), "0/2 * * * * ?");
        ScheduledTask fooTask = taskRegistrar.scheduleCronTask(cronTask);

        ExecutorService executor = Executors.newSingleThreadExecutor(Thread::new);

        executor.execute(() -> {
            try {
                // 等10秒
                TimeUnit.SECONDS.sleep(10);
                Runnable runnable = fooTask.getTask().getRunnable();
                // 停止foo任务
                fooTask.cancel();
                // 重新添加,并修改触发时间为每3秒一次
                taskRegistrar.scheduleCronTask(new CronTask(runnable, "0/3 * * * * ?"));
                // 再添加一个bar任务,每秒执行一次
                taskRegistrar.scheduleCronTask(new CronTask(() -> log.info("bar..."), "0/1 * * * * ?"));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
}

日志如下,从日志中可以看到,上面的操作是成功的,而且也是非常方便的,可以很方便的动态添加定时任务,其余几个方法就不写出来了,感兴趣的可以自己试一下。

2023-04-28 16:38:21.547  INFO 8592 --- [           main] com.example.SpringBootQuartzApplication  : Started SpringBootQuartzApplication in 1.101 seconds (JVM running for 1.563)
2023-04-28 16:38:22.002  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:24.001  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:26.001  INFO 8592 --- [    scheduler-2] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:28.001  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:30.002  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:32.002  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:33.000  INFO 8592 --- [    scheduler-2] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:33.000  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:34.002  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:35.001  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:36.001  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:36.001  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:37.002  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:38.002  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar
2023-04-28 16:38:39.001  INFO 8592 --- [    scheduler-1] com.example.task.SchedulerConfig         : foo-----------
2023-04-28 16:38:39.001  INFO 8592 --- [    scheduler-3] com.example.task.SchedulerConfig         : bar

当然,上面的例子中,因为都是在run方法内,所以没那么多讲究,一般在正式使用的时候,会在scheduleXXXTask返回的ScheduledTask实例保存起来,比如保存到map中并给一个唯一key之类的,以方便后续操作,又或者自定义类实现Runable接口并在其中指定能唯一标识这个任务的方法。具体如何实现,就看具体场景了。

quartz以及xxl-job等框架也是非常优秀的任务调度框架,提供的功能更为强大,但对于比较简单的小项目来说,没有引入的必要,Spring Schedule已经足够用了。

到此这篇关于Spring中的Schedule动态添加修改定时任务详解的文章就介绍到这了,更多相关Schedule动态添加修改定时任务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Jackson实现API接口数据脱敏的示例详解

    基于Jackson实现API接口数据脱敏的示例详解

    用户的一些敏感数据,例如手机号、邮箱、身份证等信息,在数据库以明文存储,但在接口返回数据给浏览器(或三方客户端)时,希望对这些敏感数据进行脱敏,所以本文就给大家介绍以恶如何利用Jackson实现API接口数据脱敏,需要的朋友可以参考下
    2023-08-08
  • Java中ArrayList实现原理及基本方法

    Java中ArrayList实现原理及基本方法

    这篇文章主要介绍了Java中ArrayList实现原理及基本方法,ArrayList是开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,擅长随机访问元素,插入和删除较慢,需要的朋友可以参考下
    2023-08-08
  • 完美解决idea无法搜索下载插件的问题

    完美解决idea无法搜索下载插件的问题

    这篇文章主要介绍了完美解决idea无法搜索下载插件的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • java中orElse和orElseGet方法区别小结

    java中orElse和orElseGet方法区别小结

    这篇文章主要给大家介绍了关于java中orElse和orElseGet方法区别的相关资料,两者之间的区别细微,但是却在某些场景下显的很重要,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Java中前台往后台传递多个id参数的实例

    Java中前台往后台传递多个id参数的实例

    下面小编就为大家带来一篇Java中前台往后台传递多个id参数的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java SpringMVC异常处理机制详解

    Java SpringMVC异常处理机制详解

    这篇文章主要介绍了springmvc如何进行异常处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-09-09
  • MyBatis增删改查快速上手

    MyBatis增删改查快速上手

    这篇文章给大家讲解的是MyBatis 这门技术的 CURD (增删改查) ,非常的详细与实用,有需要的小伙伴可以参考下
    2020-02-02
  • JPA @Basic单表查询如何实现大字段懒加载

    JPA @Basic单表查询如何实现大字段懒加载

    这篇文章主要介绍了JPA @Basic单表查询如何实现大字段懒加载的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 教你怎么用SpringBoot整合Swagger作为API

    教你怎么用SpringBoot整合Swagger作为API

    这篇文章主要介绍了教你怎么用SpringBoot整合Swagger作为API,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-05-05
  • mac系统刚安装的idea打不开的问题及解决

    mac系统刚安装的idea打不开的问题及解决

    这篇文章主要介绍了mac系统刚安装的idea打不开的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09

最新评论