SpringBoot中如何配置并实现定时任务调度?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2594个文字,预计阅读时间需要11分钟。
前言:在JAVA开发领域,目前可以通过以下几种方式实现定时任务:
1. Timer:JDK自带的一个定时调度类,可以简单地实现按一定频率执行任务。
提供的功能比较单一,无法实现复杂的调度。
前言
在JAVA开发领域,目前可以通过以下几种方式进行定时任务:
- Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。
- ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
- Spring Task:Spring提供的一个任务调度工具,支持注解和配置文件形式,支持Cron表达式,使用简单但功能强大。
- Quartz:一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度,就是配置稍显复杂。
题外话:对于Quartz,早前用过1.6版本的,更新到2.x及以上版本后基本没怎么接触了,原来还有倒腾过结合Kettle做了一些动态的定时抽取数据啥的还编写过一个Cron表达式编辑器,现在基本忘记了。。等有机会,再次深入学习后再来单独分享一些关于的Quartz心得吧。
基于JDK方式实现简单定时
刚刚有介绍过,基于JDK方式一共有两种:Timer和ScheduledExecutorService。接下来,就简单讲解下这两种方式。
Timer
Timer是jdk提供的java.util.Timer类。
简单示例:
@GetMapping("/timer") public String doTimer() { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { log.info("Timer定时任务启动:" + new Date()); } }, 1000,1000);//延迟1秒启动,每1秒执行一次 return "timer";启动后,访问即可看见控制台周期性输出信息了:
2018-08-18 21:30:35.171 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:35 CST 2018 2018-08-18 21:30:36.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:36 CST 2018 2018-08-18 21:30:37.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:37 CST 2018 2018-08-18 21:30:38.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:38 CST 2018 2018-08-18 21:30:39.174 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:39 CST 2018 ......相关API简单说明:
- 1、在特定时间执行任务,只执行一次
- 2、在特定时间之后执行任务,只执行一次
- 3、指定第一次执行的时间,然后按照间隔时间,重复执行
- 4、在特定延迟之后第一次执行,然后按照间隔时间,重复执行
- 5、第一次执行之后,特定频率执行,与3同
- 6、在delay毫秒之后第一次执行,后按照特定频率执行
参数:
- delay: 延迟执行的毫秒数,即在delay毫秒之后第一次执行
- period:重复执行的时间间隔
取消任务使用:timer.cancel()方法即可注销任务。
此类相对用的较少了,简单了解下。
ScheduledExecutorService
ScheduledExecutorService可以说是Timer的替代类,因为Timer不支持多线程,任务是串行的,而且也不捕获异常,假设某个任务异常了,整个Timer就无法运行了。
简单示例:
@GetMapping("/executor") public String ScheduledExecutorService() { // ScheduledExecutorService service = Executors.newScheduledThreadPool(10); service.scheduleAtFixedRate(new Runnable() { @Override public void run() { log.info("ScheduledExecutorService定时任务执行:" + new Date()); } }, 1, 1, TimeUnit.SECONDS);//首次延迟1秒,之后每1秒执行一次 log.info("ScheduledExecutorService定时任务启动:" + new Date()); return "ScheduledExecutorService!"; }启动后,可看见控制台按设定的频率输出:
2018-08-18 22:03:24.840 INFO 6752 --- [nio-8080-exec-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务启动:Sat Aug 18 22:03:24 CST 2018 2018-08-18 22:03:25.841 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:25 CST 2018 2018-08-18 22:03:26.842 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:26 CST 2018 2018-08-18 22:03:27.841 INFO 6752 --- [pool-1-thread-2] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:27 CST 2018 2018-08-18 22:03:28.840 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:28 CST 2018 2018-08-18 22:03:29.840 INFO 6752 --- [pool-1-thread-3] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:29 CST 2018可同时设置多个任务,只需再次设置scheduleAtFixedRate即可。
常用方法说明:
- ScheduleAtFixedRate:
参数说明:
-
0.command:执行线程
-
1.initialDelay:初始化延时
-
2.period:两次开始执行最小间隔时间
-
3.unit:计时单位
-
ScheduleWithFixedDelay:
参数说明:
- 0.command:执行线程
- 1.initialDelay:初始化延时
- 2.delay:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
- 3.unit:计时单位
其他的方法大家可自行谷歌下。
基于SpingTask实现定时任务
使用SpringTask在SpringBoot是很简单的,使用@Scheduled注解即可轻松搞定。
- 0.启动类,加入@EnableScheduling让注解@Scheduled生效。
- 1.编写一个调度类,系统启动后自动扫描,自动执行。
- 2.启动后,控制台可就看见每5秒一次输出了:
使用都是简单的,现在我们来看看注解@Scheduled的参数意思:
- 1.fixedRate:定义一个按一定频率执行的定时任务
- 2.fixedDelay:定义一个按一定频率执行的定时任务,与上面不同的是,改属性可以配合initialDelay, 定义该任务延迟执行时间。
- 3.cron:通过表达式来配置任务执行时间
Cron表达式详解
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
依次顺序如下表所示:
字段 允许值 允许的特殊字符 秒 0~59 , – * / 分 0~59 , – * / 小时 0~23 , – * / 日期 1-31 , – * ? / L W C 月份 1~12或者JAN~DEC , – * / 星期 1~7或者SUN~SAT , – * ? / L C # 年(可选) 留空,1970~2099 , – * /简单举例:
- 0/1 * * * * ?:每秒执行一次
- 0 0 2 1 * ? : 表示在每月的1日的凌晨2点调整任务
- 0 0 10,14,16 ? :每天上午10点,下午2点,4点
- 0 0 12 * * ? : 每天中午12点触发
- 0 15 10 ? * MON-FRI : 周一至周五的上午10:15触发
更多表达式,可访问:cron.qqe2.com/ 进行在线表达式编写。简单明了。
自定义线程池
从控制台输出可以看见,多任务使用的是同一个线程。可结合上章节的异步调用来实现不同任务使用不同的线程进行任务执行。
- 0.编写配置类,同时启用@Async注解:
- 1.调度类上加入@Async。
再次启动程序,可看见控制台输出,任务已经是不同线程下执行了:
2018-08-18 22:47:13.313 INFO 14212 --- [ong-Scheduled-1] c.l.l.s.c.controller.ScheduledTask : Scheduled定时任务执行:Sat Aug 18 22:47:13 CST 2018 2018-08-18 22:47:13.343 INFO 14212 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (github.com/redisson/redisson有兴趣的同学可以了解下。可构建一个纯粹的定时服务,只有定时器相关配置,比如定时时间,定时调度的api接口或者www.cnblogs.com/yank/p/3955322.html
总结
本章节主要是讲解了通过不同的方式实现定时任务。对于定时任务而言,本身是门大学问,一俩篇文章是讲不完的。像SpringTask和Quartz都是很强大的调度器,两者很相似,像如何实现任务的动态修改调度周期,动态停止相关任务,调度任务的监控,这些本文章都没有涉及。还希望有相关需求的同学自行搜索相关资料了。
本文共计2594个文字,预计阅读时间需要11分钟。
前言:在JAVA开发领域,目前可以通过以下几种方式实现定时任务:
1. Timer:JDK自带的一个定时调度类,可以简单地实现按一定频率执行任务。
提供的功能比较单一,无法实现复杂的调度。
前言
在JAVA开发领域,目前可以通过以下几种方式进行定时任务:
- Timer:jdk中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行。提供的功能比较单一,无法实现复杂的调度任务。
- ScheduledExecutorService:也是jdk自带的一个基于线程池设计的定时任务类。其每个调度任务都会分配到线程池中的一个线程执行,所以其任务是并发执行的,互不影响。
- Spring Task:Spring提供的一个任务调度工具,支持注解和配置文件形式,支持Cron表达式,使用简单但功能强大。
- Quartz:一款功能强大的任务调度器,可以实现较为复杂的调度功能,如每月一号执行、每天凌晨执行、每周五执行等等,还支持分布式调度,就是配置稍显复杂。
题外话:对于Quartz,早前用过1.6版本的,更新到2.x及以上版本后基本没怎么接触了,原来还有倒腾过结合Kettle做了一些动态的定时抽取数据啥的还编写过一个Cron表达式编辑器,现在基本忘记了。。等有机会,再次深入学习后再来单独分享一些关于的Quartz心得吧。
基于JDK方式实现简单定时
刚刚有介绍过,基于JDK方式一共有两种:Timer和ScheduledExecutorService。接下来,就简单讲解下这两种方式。
Timer
Timer是jdk提供的java.util.Timer类。
简单示例:
@GetMapping("/timer") public String doTimer() { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { log.info("Timer定时任务启动:" + new Date()); } }, 1000,1000);//延迟1秒启动,每1秒执行一次 return "timer";启动后,访问即可看见控制台周期性输出信息了:
2018-08-18 21:30:35.171 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:35 CST 2018 2018-08-18 21:30:36.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:36 CST 2018 2018-08-18 21:30:37.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:37 CST 2018 2018-08-18 21:30:38.173 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:38 CST 2018 2018-08-18 21:30:39.174 INFO 13352 --- [ Timer-0] c.l.l.s.c.controller.TaskController : Timer定时任务启动:Sat Aug 18 21:30:39 CST 2018 ......相关API简单说明:
- 1、在特定时间执行任务,只执行一次
- 2、在特定时间之后执行任务,只执行一次
- 3、指定第一次执行的时间,然后按照间隔时间,重复执行
- 4、在特定延迟之后第一次执行,然后按照间隔时间,重复执行
- 5、第一次执行之后,特定频率执行,与3同
- 6、在delay毫秒之后第一次执行,后按照特定频率执行
参数:
- delay: 延迟执行的毫秒数,即在delay毫秒之后第一次执行
- period:重复执行的时间间隔
取消任务使用:timer.cancel()方法即可注销任务。
此类相对用的较少了,简单了解下。
ScheduledExecutorService
ScheduledExecutorService可以说是Timer的替代类,因为Timer不支持多线程,任务是串行的,而且也不捕获异常,假设某个任务异常了,整个Timer就无法运行了。
简单示例:
@GetMapping("/executor") public String ScheduledExecutorService() { // ScheduledExecutorService service = Executors.newScheduledThreadPool(10); service.scheduleAtFixedRate(new Runnable() { @Override public void run() { log.info("ScheduledExecutorService定时任务执行:" + new Date()); } }, 1, 1, TimeUnit.SECONDS);//首次延迟1秒,之后每1秒执行一次 log.info("ScheduledExecutorService定时任务启动:" + new Date()); return "ScheduledExecutorService!"; }启动后,可看见控制台按设定的频率输出:
2018-08-18 22:03:24.840 INFO 6752 --- [nio-8080-exec-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务启动:Sat Aug 18 22:03:24 CST 2018 2018-08-18 22:03:25.841 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:25 CST 2018 2018-08-18 22:03:26.842 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:26 CST 2018 2018-08-18 22:03:27.841 INFO 6752 --- [pool-1-thread-2] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:27 CST 2018 2018-08-18 22:03:28.840 INFO 6752 --- [pool-1-thread-1] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:28 CST 2018 2018-08-18 22:03:29.840 INFO 6752 --- [pool-1-thread-3] c.l.l.s.c.controller.TaskController : ScheduledExecutorService定时任务执行:Sat Aug 18 22:03:29 CST 2018可同时设置多个任务,只需再次设置scheduleAtFixedRate即可。
常用方法说明:
- ScheduleAtFixedRate:
参数说明:
-
0.command:执行线程
-
1.initialDelay:初始化延时
-
2.period:两次开始执行最小间隔时间
-
3.unit:计时单位
-
ScheduleWithFixedDelay:
参数说明:
- 0.command:执行线程
- 1.initialDelay:初始化延时
- 2.delay:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
- 3.unit:计时单位
其他的方法大家可自行谷歌下。
基于SpingTask实现定时任务
使用SpringTask在SpringBoot是很简单的,使用@Scheduled注解即可轻松搞定。
- 0.启动类,加入@EnableScheduling让注解@Scheduled生效。
- 1.编写一个调度类,系统启动后自动扫描,自动执行。
- 2.启动后,控制台可就看见每5秒一次输出了:
使用都是简单的,现在我们来看看注解@Scheduled的参数意思:
- 1.fixedRate:定义一个按一定频率执行的定时任务
- 2.fixedDelay:定义一个按一定频率执行的定时任务,与上面不同的是,改属性可以配合initialDelay, 定义该任务延迟执行时间。
- 3.cron:通过表达式来配置任务执行时间
Cron表达式详解
一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。
依次顺序如下表所示:
字段 允许值 允许的特殊字符 秒 0~59 , – * / 分 0~59 , – * / 小时 0~23 , – * / 日期 1-31 , – * ? / L W C 月份 1~12或者JAN~DEC , – * / 星期 1~7或者SUN~SAT , – * ? / L C # 年(可选) 留空,1970~2099 , – * /简单举例:
- 0/1 * * * * ?:每秒执行一次
- 0 0 2 1 * ? : 表示在每月的1日的凌晨2点调整任务
- 0 0 10,14,16 ? :每天上午10点,下午2点,4点
- 0 0 12 * * ? : 每天中午12点触发
- 0 15 10 ? * MON-FRI : 周一至周五的上午10:15触发
更多表达式,可访问:cron.qqe2.com/ 进行在线表达式编写。简单明了。
自定义线程池
从控制台输出可以看见,多任务使用的是同一个线程。可结合上章节的异步调用来实现不同任务使用不同的线程进行任务执行。
- 0.编写配置类,同时启用@Async注解:
- 1.调度类上加入@Async。
再次启动程序,可看见控制台输出,任务已经是不同线程下执行了:
2018-08-18 22:47:13.313 INFO 14212 --- [ong-Scheduled-1] c.l.l.s.c.controller.ScheduledTask : Scheduled定时任务执行:Sat Aug 18 22:47:13 CST 2018 2018-08-18 22:47:13.343 INFO 14212 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (github.com/redisson/redisson有兴趣的同学可以了解下。可构建一个纯粹的定时服务,只有定时器相关配置,比如定时时间,定时调度的api接口或者www.cnblogs.com/yank/p/3955322.html
总结
本章节主要是讲解了通过不同的方式实现定时任务。对于定时任务而言,本身是门大学问,一俩篇文章是讲不完的。像SpringTask和Quartz都是很强大的调度器,两者很相似,像如何实现任务的动态修改调度周期,动态停止相关任务,调度任务的监控,这些本文章都没有涉及。还希望有相关需求的同学自行搜索相关资料了。

