SpringBoot基础教程3-1-1 简单定时任务方法介绍
1 概述
定时任务,特定的时间执行任务,在项目中普遍使用。本文介绍简单的无状态无持久化的定时任务实现方式;Timer
,ScheduledExecutorService
,Spring Task
。
2 Timer
实现方式
JDK
自带的java.util.Timer
;通过调度java.util.TimerTask
的方式 让程序按照某一个频度执行,但不能在指定时间运行。 一般用的较少。
/**
* 基于 Timer 实现的定时调度,基本就是手撸代码,目前应用较少,不是很推荐
*
* @author Mkeeper
* @create 2018/9/28 11:12
*/
public class TimerDemo {
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("执行任务: " + LocalDateTime.now());
}
};
Timer timer = new Timer();
// timerTask:需要执行的任务
// delay:延迟时间(以毫秒为单位)
// period:间隔时间(以毫秒为单位)
timer.schedule(timerTask, 5000, 3000);
}
}
3 ScheduledExecutorService
实现方式
ScheduledExecutorService
,JDK1.5新增的,位于java.util.concurrent
包中;是基于线程池设计的定时任务类,每个调度任务都会被分配到线程池中,并发执行,互不影响。
与Timer
很类似,但它的效果更好;多线程并行处理定时任务时,Timer
运行多个TimeTask
时,只要其中有一个因任务报错没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService
则可以规避这个问题
/**
* 优于Timer
* @author Mkeeper
* @create 2018/9/28 11:15
*/
public class ScheduledExecutorServiceDemo {
public static void main(String[] args) {
final ScheduledExecutorService service = Executors.newScheduledThreadPool(3);
// 参数:
// 1、具体执行的任务
// 2、首次执行的延时时间
// 3、任务执行间隔
// 4、间隔时间单位
service.scheduleAtFixedRate(() ->
System.out.println("执行任务:" + LocalDateTime.now()),
0, 3, TimeUnit.SECONDS
);
}
}
4 Spring Task
实现方式(推荐)
Spring Task
, Spring3.0
以后新增了task
,一个轻量级的Quartz
,功能够用,用法简单。
Spring Task
在spring-context
的org.springframework.scheduling
下,只需要依赖spring-boot-starter-web
即可。
@Scheduled
注解,Spring Task
定时任务的核心
-
cron
:cron
表达式,根据表达式循环执行,与fixedRate
属性不同的是它是将时间进行了切割。@Scheduled(cron = "0/5 * * * * *"
任务将在5、10、15、20...
这种情况下执行。 -
fixedRate
: 每隔多久执行一次;@Scheduled(fixedRate = 1000
假设第一次工作时间为2018-09-28 10:58:28
,工作时长为3秒,那么下次任务的时候就是2018-09-28 10:58:31
;配置成异步后,只要到了执行时间就会开辟新的线程工作,如果@Scheduled(fixedRate = 1000
假设第一次工作时间为2018-09-28 10:58:28
,工作时长为3秒,那么下次任务的时间是2018-09-28 10:58:29
。 -
fixedDelay
: 当前任务执行完毕后等待多久继续下次任务@Scheduled(fixedDelay = 3000
假设第一次任务工作时间为2018-09-28 10:58:30
,工作时长为5秒,那么下次任务的时间就是2018-09-28 10:58:38
。 -
initialDelay
: 第一次执行延迟时间,只是做延迟的设定,与fixedDelay
关系密切,配合使用,相辅相成。
@Async
注解,代表该任务可以进行异步工作,由串行改为并行。
cron表达式在线生成: http://www.pdtools.net/tools/becron.jsp
@Component
@Slf4j
public class SpringTaskDemo {
@Async
@Scheduled(cron = "0/1 * * * * *")
public void scheduled1() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
log.info("schedule1 每1m秒执行一次: {}", LocalDateTime.now());
}
@Scheduled(fixedRate = 1000)
public void scheduled2() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
log.info("schedule2 每1m秒执行一次: {}", LocalDateTime.now());
}
@Scheduled(fixedDelay = 3000)
public void scheduled3() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
log.info("scheduled3 上次执行完毕后隔3秒继续执行:{}", LocalDateTime.now());
}
}
开启任务
-
@EnableScheduling
注解表示开启对@Scheduled
注解的解析;同时new ThreadPoolTaskScheduler()
也是相当的关键,通过阅读过源码可以发现默认情况下的private volatile int poolSize = 1
;这就导致了多个任务的情况下容易出现竞争情况,多个任务的情况下,如果第一个任务没执行完毕,后续的任务将会进入等待状态。 -
@EnableAsync
注解表示开启@Async
注解的解析;作用就是将串行化的任务给并行化。
@EnableAsync
@EnableScheduling
@Configuration
public class TaskSchedulerConfig {
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(10);
return taskScheduler;
}
}
5 测试结果
请自己动动手
6 工程目录
7 结束语
后续文章会陆续介绍,Quartz
,以及基于Quartz
实现的分布式任务项目,xxl-job
,elastic-job
,尽情期待。本文源码。
欢迎关注博主公众号,第一时间推送最新文章