Java 杂谈

SpringBoot定时任务

2019-03-21  本文已影响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/
上一篇下一篇

猜你喜欢

热点阅读