美文网首页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