SpringBoot 2.x 简单启用定时任务

252 阅读3分钟

这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战

定时任务有以下几种常用的实现方式,本文主要讲解一下 Spring Task 的用法。

  • Timer: JDK 自带的 java.util.Timer;通过调度 java.util.TimerTask 的方式让程序按照某一个频度执行,但不能在指定时间运行。
  • ScheduledExecutorService: JDK1.5 新增的,位于 java.util.concurrent 包中;是基于线程池设计的定时任务类,每个调度任务都会被分配到线程池中,并发执行,互不影响。
  • Spring Task: Spring 3.0 以后新增了 task 组件,一个轻量级的 Quartz,功能够用,用法简单。
  • Quartz: 功能最为强大的调度器,可以让程序在指定时间执行,也可以按照某一个频度执行,它还可以动态开关,但是配置起来比较复杂。

Spring Task

需要依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

代码样例

TaskApplication.java 入口函数

package cn.aurthur.sbdemo.task;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@EnableAsync
@EnableScheduling
@SpringBootApplication
public class TaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskApplication.class, args);
    }

    /**
     * 很关键:默认情况下 TaskScheduler 的 poolSize = 1
     *
     * @return 线程池
     */
    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        return taskScheduler;
    }
}

TaskDemo.java 定时任务实现

package cn.aurthur.sbdemo.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class TaskDemo {
    private static final Logger log = LoggerFactory.getLogger(TaskDemo.class);

    @Async
    @Scheduled(cron = "0/1 * * * * *")
    public void scheduled1() throws InterruptedException {
        Thread.sleep(3000);
        log.info("scheduled1 每1秒执行一次:{}", LocalDateTime.now());
    }

    @Scheduled(fixedRate = 1000)
    public void scheduled2() throws InterruptedException {
        Thread.sleep(3000);
        log.info("scheduled2 每1秒执行一次:{}", LocalDateTime.now());
    }

    @Scheduled(fixedDelay = 3000)
    public void scheduled3() throws InterruptedException {
        Thread.sleep(5000);
        log.info("scheduled3 上次执行完毕后隔3秒继续执行:{}", LocalDateTime.now());
    }
}

使用说明

@Scheduled 定时任务的核心

  • cron: cron表达式,根据表达式循环执行,与 fixedRate 属性不同的是它是将时间进行了切割。(@Scheduled(cron = "0/5 * * * * *")任务将在5、10、15、20...这种情况下进行工作)
  • fixedRate: 每隔多久执行一次;(@Scheduled(fixedRate = 1000) 假设第一次工作时间为2018-05-29 16:58:28,工作时长为3秒,那么下次任务的时候就是2018-05-29 16:58:31,配置成异步后,只要到了执行时间就会开辟新的线程工作),如果(@Scheduled(fixedRate = 3000) 假设第一次工作时间为2018-05-29 16:58:28,工作时长为1秒,那么下次任务的时间依然是2018-05-29 16:58:31)
  • fixedDelay: 当前任务执行完毕后等待多久继续下次任务(@Scheduled(fixedDelay = 3000) 假设第一次任务工作时间为2018-05-29 16:54:33,工作时长为5秒,那么下次任务的时间就是2018-05-29 16:54:41)
  • initialDelay: 第一次执行延迟时间,只是做延迟的设定,与 fixedDelay 关系密切,配合使用,相辅相成。

@Async 代表该任务可以进行异步工作,由原本的串行改为并行

@Component 将 TaskDemo 类加入 Spring 管理

cron 表达式

cron 格式解析:* * * * * *

  • Seconds(秒)
  • Minutes(分)
  • Hours(时)
  • Day-of-Month(日)
  • Month(月)
  • Day-of-Week(星期)
  • Year(可选字段)(年)