美文网首页Java 杂谈
SpringBoot定时任务

SpringBoot定时任务

作者: 我是曾经那个少年 | 来源:发表于2019-03-21 13:43 被阅读123次

    业务中例如:每隔几秒获取订单支付状态,30分钟为支付的订单需要取消订单,固定把前一天的的活动数据汇总等业务就需要定时任务来处理这部分需求。

    那SpringBoot怎么开箱即用?

    1 Spring定时任务快速上手

    1. https://start.spring.io/初始化一个空项目,不需要添加其他任何配置。

    2. 使用@EnableScheduling再启动类上面开启定时任务配置。

    @SpringBootApplication
    @EnableScheduling
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    
    1. 新建一个类添加@Component注解,并且在方法上添加@Scheduled注解配置任务怎么执行
    @Component
    public class TaskCorn {
    
        private static Logger logger = LoggerFactory.getLogger(TaskCorn.class);
    
        /**
         * 任务固定延时多久
         * @throws InterruptedException
         */
        @Scheduled(fixedDelay = 2000)
        public void taskFixedDelay() throws InterruptedException {
            logger.info("taskFixedDelay开始:{}", System.currentTimeMillis());
            Thread.sleep(60000);
            logger.info("taskFixedDelay结束:{}", System.currentTimeMillis());
        }
        
        /**
         * 任务固定频率
         * @throws InterruptedException
         */
        @Scheduled(initialDelay=1000,fixedRate = 2000)
        public void taskFixedRate() throws InterruptedException {
            logger.info("taskFixedRate开始:{}", System.currentTimeMillis());
            Thread.sleep(6000);
            logger.info("taskFixedRate结束:{}", System.currentTimeMillis());
        }
        
    }
    
    1. @Scheduled注解说明

    @Scheduled代码内容如下:

        // cron表达式
        String cron() default "";
    
        String zone() default "";
    
        // 固定延迟,也就是上一次执行完成等待多久
        long fixedDelay() default -1;
        String fixedDelayString() default "";
    
        // 固定频率,也就是上一次开始执行等待多久
        long fixedRate() default -1;
        String fixedRateString() default "";
    
        // 初始化多久后在执行
        long initialDelay() default -1;
        String initialDelayString() default "";
    

    常用:

    @Scheduled(fixedDelay = 2000)

    上次任务执行完成后等待两秒进行下一次执行。

    @Scheduled(fixedRate = 2000)

    上次任务执行开始后等待两秒进行下一次执行。

    @Scheduled(cron="0 0/20 * * * ?")

    每二十分钟执行一次

    @Scheduled(cron="0 1 0 * * ?")

    每天零点1分执行一次

    1. 查看运行结果
    2019-03-21 11:34:30.563  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedDelay结束:1553139270563
    2019-03-21 11:34:30.563  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553139270563
    2019-03-21 11:34:36.565  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553139276565
    2019-03-21 11:34:36.566  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553139276566
    2019-03-21 11:34:42.567  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553139282567
    2019-03-21 11:34:42.567  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553139282567
    2019-03-21 11:34:48.568  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553139288568
    2019-03-21 11:34:48.568  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553139288568
    2019-03-21 11:34:54.569  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553139294569
    2019-03-21 11:34:54.569  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedDelay开始:1553139294569
    2019-03-21 11:35:00.571  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedDelay结束:1553139300571
    2019-03-21 11:35:00.572  INFO 18676 --- [pool-1-thread-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553139300572
    

    我们发现定个定时任务都是使用的pool-1-thread-1这个名称的线程。这就是SpringBoot默认的是单线程。

    所以为了能在生成环境使用,避免多任务单线程,有一个线程挂起导致项目bug。还有项目出了问题,我们怎么可以第一时间知道。

    So需要

    1. 配置多线程
    2. 增加错误预警

    2 Spring定时任务完善

    重新实现SchedulingConfigurer的configureTasks配置线程池。

    @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            ThreadPoolTaskScheduler handler = new ThreadPoolTaskScheduler();
            handler.setPoolSize(10);
            handler.setThreadNamePrefix("schedule-");
            handler.setAwaitTerminationSeconds(60);
            handler.setErrorHandler(new ErrorHandler() {
    
                @Override
                public void handleError(Throwable t) {
                    logger.info("异常统一处理......" + t.getMessage());
                    // 发送邮件
                    // 发送短信
                }
            });
            handler.initialize();
            taskRegistrar.setScheduler(handler);
        }
    

    查看运行结果:可以看到两个任务使用的是不同的线程名。

    2019-03-21 11:47:04.347  INFO 15252 --- [     schedule-5] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553140024347
    2019-03-21 11:47:04.347  INFO 15252 --- [     schedule-5] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553140024347
    2019-03-21 11:47:07.358  INFO 15252 --- [     schedule-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedDelay结束:1553140027358
    2019-03-21 11:47:09.360  INFO 15252 --- [     schedule-1] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedDelay开始:1553140029360
    2019-03-21 11:47:10.347  INFO 15252 --- [     schedule-5] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate结束:1553140030347
    2019-03-21 11:47:10.347  INFO 15252 --- [     schedule-5] c.liuawei.spring.scheduler.job.TaskCorn  : taskFixedRate开始:1553140030347
    

    ???:有的时候定时任务处理非常耗时,但是我们需要任务能快速完成,所以我们需要在定时任务中需要异步执行(或者多个线程执行)。这种情况肿么办?大家可以思考下。后面会完善。

    源码下载github

    参考文档:

    官方教程:
    https://spring.io/guides/gs/scheduling-tasks/
    

    相关文章

      网友评论

        本文标题:SpringBoot定时任务

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