这是我参与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(可选字段)(年)