美文网首页Java web
框架篇-定时任务(二) - Spring Task

框架篇-定时任务(二) - Spring Task

作者: 秃头猿猿 | 来源:发表于2020-04-28 13:24 被阅读0次

    1.定时任务-Spring Task

    通过先前的例子,我们使用jdk自带的定时器实现了定时任务,当然我们也可以采用spring给我们提供的定时任务处理模块Spring Scheduler.

    1.2 例子-helloworld

    1.2.1 新建项目

    image-20200428111024028.png image-20200428111040941.png

    注意:没有导入任何依赖

    1.2.2 编码

    • 撰写任务

      package com.spring.task.demo.task;
      
      import org.springframework.scheduling.annotation.Scheduled;
      import org.springframework.stereotype.Component;
      
      @Component
      public class Task {
      
          @Scheduled(cron = "*/10 * * * * ?")
          public void test1() {
              System.out.println("====== 任务1 ====");
          }
      }
      
      
    • 在启动类上加上@EnableScheduling

      image-20200428112519855.png
    • 启动程序(每隔10s执行一次)

      image-20200428112711464.png

    1.2.3 helloword解析

    image-20200428112853564.png

    从上图中我们可以看出,方法test1上面加入了@Scheduled注解。

    • @Scheduled

      这个注解加在方法上,将一个普通的方法声明为一个任务。到时候被调度。

    • cron 是一个表达式。不同的*代表着不同的涵义。其格式为秒 分 时 日 月 周 年 具体用法如下所示:

      字段名 允许的值 特殊字符
      0 - 59 , - * /
      0 - 59 , - * /
      0 - 23 , - * /
      0 - 31 , - * ? / L W
      1 - 12 或 JAN - DEC , - * /
      1 - 7 或 SUN - SAT , - * ? / L #
      年(可选) empty 或 1970 - 2099 , - * /
    • 特殊字符含义如下:

      , 指定数个值

      - 指定一个值的范围

      * 表示任何可能的值

      / 指定一个值的增加幅度。 n / m 表示 从 n 开始,每次增加 m

      ? 表示不确定的值

      L 用在 日 表示一个月的最后一天,用在周表示该月最后的一个星期X

      W 指定离给定日期最近的工作日(周一到周五)

      # 表示该月的第几个周X,6#3 表示该月第三个周五

    • 练习:

      每隔五秒执行一次 */5 * * * * ?

      每隔1分钟执行一次 0 */1 * * * ?

      每天2点执行一次 0 0 2 * * * ?

      每个月1号1点执行一次 0 0 1 1 * ?

      每天 0点 13点执行 1次 0 0 0,13 * * ?

      当然你如果不熟悉,或者是一下不能够想起这种语法怎么办。我们可以采用一些工具帮我们生成 cron表示式子

      工具地址: https://www.pppet.net/

      image-20200428124006443.png

    例如每个月 3号 9号的6点和9点执行一次,用工具就可以快速生成:

    image-20200428124349247.png
    • 启动类

      一定要在启动类上加上@EnableScheduling注解,这个注解就是开启任务调度

    1.2.4 其他特性

    我们通过cron表达式可以指定任务的运行,当然我们也可以去使用其他的方式去运行

    • 上次任务完成后,1毫秒执行,也就是间隔1毫秒执行

      image-20200428124540140.png
    • 第一次立马执行,然后间隔五秒执行

      image-20200428125126042.png
    • 第一次延迟3秒执行,以后每个五秒执行

      image-20200428125338305.png

    1. 串行任务

    通过helloword我们明白了spring task 基本用法,接下来我们分析如果时多个任务,那么时串行的还是并行的。

    • 测试代码:

      package com.spring.task.demo.task;
      
      import org.springframework.scheduling.annotation.Scheduled;
      import org.springframework.stereotype.Component;
      
      @Component
      public class Task {
      
          @Scheduled(fixedRate = 1000)
          public void test1() {
              System.out.println("====== 任务1 开始 ====");
              try {
                  Thread.sleep(3000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println("====== 任务1 结束 ====");
          }
      
          @Scheduled(fixedRate = 1000)
          public void test2() {
              System.out.println("====== 任务2 开始 ====");
              try {
                  Thread.sleep(3000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println("====== 任务2 结束 ====");
          }
      
      }
      
      
      image-20200428125936776.png

    从结果发现,当任务1结束以后,才能够执行任务2.这是因为默认采用的时串行任务策略。但在实际开发过程中,如果有多个任务,且任务之间互不相关,那么应该采用并行任务才合理。

    1.4 并行任务

    要将将默认的串行任务修改成串行任务,那么我们只需要写一个任务调度的配置类即可。

    其实原理差不多,让线程池里面的一个线程去执行任务,不同的线程执行不同的任务

    • 代码和解释如下:

      package com.spring.task.demo.config;
      
      import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.scheduling.annotation.AsyncConfigurer;
      import org.springframework.scheduling.annotation.SchedulingConfigurer;
      import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
      import org.springframework.scheduling.config.ScheduledTaskRegistrar;
      
      import java.util.concurrent.Executor;
      
      /**
       * 并行任务配置类
       */
      @Configuration
      public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer {
      
          /**
           * 线程池线程数量
           */
          private int corePoolSize = 5;
      
          /**
           * 创建线程池
           */
          @Bean
          public ThreadPoolTaskScheduler taskScheduler() {
              ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
              scheduler.initialize();
              scheduler.setPoolSize(corePoolSize);
              return scheduler;
          }
      
          @Override
          public Executor getAsyncExecutor() {
              return taskScheduler();
          }
      
          @Override
          public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
              return null;
          }
      
          @Override
          public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
              // 设置线程池
              taskRegistrar.setTaskScheduler(taskScheduler());
          }
      }
      
      
      image-20200428131942508.png

      我们可以看见几乎同时开始任务,并且互不影响。

    相关文章

      网友评论

        本文标题:框架篇-定时任务(二) - Spring Task

        本文链接:https://www.haomeiwen.com/subject/vievwhtx.html