Spring定时任务高级使用篇
Spring定时任务高级使用篇
前面一篇博文 《Spring之定时任务基本使用篇》 介绍了Spring环境下,定时任务的简单使用姿势,也留了一些问题,这一篇则希望能针对这些问题给个答案
I. 定时任务进阶篇
1. 问题小结
前面一篇博文,抛出了下面的几个问题,接下来则围绕问题进行分析
- 一个项目中有多个定时任务时,他们是并行执行的还是串行执行的?
如果默认是串行的
- 那么有相同的crond表达式的定时任务之间,有先后顺序么?
- 某个任务的阻塞是否会影响后面的任务?
- 如果需要他们并行执行,可以怎么做?
如果是并发执行的
- 是新创建线程还是采用线程池来复用呢?
- 在并发执行时,假设有个每秒执行一次的任务,但是它执行一次消耗的时间大于1s时,这个任务的表现时怎样的呢?不断地新增线程来执行还是等执行完毕之后再执行下一次的呢?
2. 多定时任务的串并行分析
如何确认一个项目中的多个定时任务是串行执行还是并发执行呢?要想验证这个功能,最好的法子就是写个testcase,比如定义两个定时任务,在其中一个任务中写个死循环,看另外一个任务是否会正常执行
@Scheduled(cron = "0/1 * * * * ?")
public void sc1() throws InterruptedException {System.out.println(Thread.currentThread().getName() + " | sc1 " + System.currentTimeMillis());while (true) {Thread.sleep(5000);}
}@Scheduled(cron = "0/1 * * * * ?")
public void sc2() {System.out.println(Thread.currentThread().getName() + " | sc2 " + System.currentTimeMillis());
}
首先我们分析的是 sc1和sc2这两个任务的执行是串行还是并行的,暂时先不考虑 sc1 调用时阻塞,下一秒是否是开新的线程再调用sc1
- 若串行:则sc1打印一次,sc2可能打印0或者1次
- 若并行:sc1打印一次,sc2打印n多次
实际运行,GIF图演示如下
上图的结果,印证了默认的情况下,多个定时任务时串行执行的;如果一个任务出现阻塞,其他的任务都会受到影响
3. 定时任务执行的优先级
既然是顺序执行的,那么优先级怎么定?每次都是固定的,还是随机的呢?
要验证上面的方法,也容易,同样两个任务,看他们的输出是否会乱掉,如果每次都是任务1打印完再打印任务2,那就是固定优先级的;否则每次调度时,顺序不好说
测试代码如下
@Scheduled(cron = "0/1 * * * * ?")
public void sc1() {System.out.println(Thread.currentThread().getName() + " | sc1 " + System.currentTimeMillis());
}@Scheduled(cron = "0/1 * * * * ?")
public void sc2() {System.out.println(Thread.currentThread().getName() + " | sc2 " + System.currentTimeMillis());
}
实测结果如下
从输出得出结论:顺序是串掉的,并没有表现出明显的优先级关系
4. 并行调度
接下来的问题就是我希望这些任务可以并发执行,可以实现么?
当然是可以,用起来也比较简单,首先是在Application上添加注解@EnableAsync
,开启异步调用,然后再计划任务上加上@Async
注解即可,一个简单的demo如下
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class QuickMediaApplication {public static void main(String[] args) {SpringApplication.run(QuickMediaApplication.class, args);}@Scheduled(cron = "0/1 * * * * ?")@Asyncpublic void sc1() {System.out.println(Thread.currentThread().getName() + " | sc1 " + System.currentTimeMillis());}
}
上面执行之后,查看输出(异步调度时,理论上线程名应该不一样)
从上面的输出,可以简单的推理,每次调度上面的任务都是新开了一个线程来做的,所以如果在定时任务中写了死循环,是否会导致无限线程,最后整个进程崩掉?
额外提一句,linux系统下单进程的线程数是有上线的,查看命令为:
ulimit -u
在测试之前,先看下上面的正常任务执行,如下面的动图,线程数并没有夸张的长法
接下来换成死循环的调度方式,实际测试如下,线程数蹭蹭的上涨
所以使用默认的异步调用方式,并不是一个好注意,说不准就被玩死了自己都不知道,那么可以用自己的线程池来管理这些异步任务么?
5. 自定义线程池
用自定义的线程池来取代默认线程管理方式,无疑是一个更加安全和灵活的方式,使用起来也并不麻烦,和平常创建线程池的套路没什么区别,要在Spring生态中使用,就把它搞成bean即可
直接借助Spring的线程池ThreadPoolTaskExecutor
@Bean
public AsyncTaskExecutor asyncTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setThreadNamePrefix("yhh-schedule-");executor.setMaxPoolSize(10);executor.setCorePoolSize(3);executor.setQueueCapacity(0);executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());return executor;
}@Scheduled(cron = "0/1 * * * * ?")
@Async
public void sc1() throws InterruptedException {System.out.println(Thread.currentThread().getName() + " | sc1 " + System.currentTimeMillis());while (true) {Thread.sleep(1000 * 5);}
}
实际演示的结果如下,最多10个线程,再提交的任务直接丢弃
简单说一下,用自定义线程池的好处:
- 合理的分配线程池参数
- 拒绝策略的选择也比较有意思(可以按照自己的想法来处理"负载"的任务)
- 线程池命名,对于以后问题排查,会有很大的帮助
6. 小结
本来这篇博文在昨天即8月2号就应该写完的,结果晚上生产环境下除了点问题,解决线上故障之后就比较晚了,留到了今天,哎,拖延症也是要不得。。。
下面小结Spring中定时任务的几个知识点
- 默认所有的定时任务都是串行调度的,一个线程,且即便crond完全相同的两个任务先后顺序也没法保证(具体原因需要源码分析,看下这块是怎么支持)
- 使用
@Async
注解可以使定时任务异步调度;但是需要开启配置,在启动类上添加@EnableAsync
注解 - 开启并发执行时,推荐用自定义的线程池来替代默认的,理由见上面
II. 其他
0. 相关
- 《Spring之定时任务基本使用篇》
1. 一灰灰Blog: https://liuyueyi.github.io/he...
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明
尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
3. 扫描关注
小灰灰Blog&公众号
知识星球
Spring定时任务高级使用篇相关推荐
- async spring 默认线程池_Spring定时任务高级使用篇
I. 定时任务进阶篇 1. 问题小结 之前写过一篇博文,抛出了下面的几个问题,接下来则围绕问题进行分析 一个项目中有多个定时任务时,他们是并行执行的还是串行执行的? 如果默认是串行的 那么有相同的cr ...
- Spring之定时任务基本使用篇
文章链接:https://liuyueyi.github.io/hexblog/2018/08/01/180801-Spring之定时任务基本使用篇/ Spring之定时任务基本使用篇 spring- ...
- Spring定时任务的几种实现
Spring定时任务的几种实现 spring框架 quartz spring spring-task 定时任务 注解 近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信 ...
- (转)Spring定时任务的几种实现
Spring定时任务的几种实现 博客分类: spring框架 quartzspringspring-task定时任务注解 Spring定时任务的几种实现 近日项目开发中需要执行一些定时任务,比如需要 ...
- Spring定时任务@scheduled多线程的使用(@Async注解)
1.开篇 在Spring定时任务@Scheduled注解使用方式浅窥这篇文章里面提及过,spring的定时任务默认是单线程的,他在某些场景下会造成堵塞,那么如果我们想让每一个任务都起一条线程去执行呢? ...
- 第七章、Spring Boot MyBatis升级篇
课时二十七.Spring Boot MyBatis升级篇-注解 缘起:在一节视频中,有这么一段留言:"会不会推出SpringBoot整合Mybaits配置文件sqlMapConfig.xml ...
- 【定时任务】——Spring定时任务Scheduled
定时任务在日常开发过程中非常常见,而且在日常的项目开发中也有多种实现方式,而且做任务调度的框架有很多种,小编最近的感受,如果想真正使用好任务调度还是存在困难的,所以分步学习,逐个击破!在这篇文章小编主 ...
- Spring定时任务@Scheduled注解使用配置方式(cron表达式、fixedRate和fixedDelay)
Spring定时任务@Scheduled注解使用配置方式(cron表达式.fixedRate和fixedDelay) 序言: 个人推荐一个很方便的在线Cron生成器(网页版):https://qqe2 ...
- 54. spring boot日志升级篇—logback【从零开始学Spring Boot】
在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...
最新文章
- 奖励名单表格模板_员工出勤工薪记算表(行政人事模板)
- C语言指针作为函数返回值
- ssh无密码登录设置(centos6系统下实现)
- 通过Xcode断点集成 reveal(2017-10-20更新)
- day 68 增删改查 语法
- navmenu 收起没有动画 element_ABC360等3家英语动画片课程测评:用动画片学英语不靠谱?...
- STM32学习——ROV遇到的坑
- Being a good boy in the spring festival NIM博弈
- 华为回怼特朗普;中兴首款 5G 上市;iPhone 可免息分期购买 | 极客头条
- 相近字符串的匹配--编辑距离问题
- 指数有限的子群存在一个右陪集代表元系,同时也是左陪集代表元系
- java迭代遍历_JAVA集合中的迭代器的遍历
- 用GHOST一键恢复之后,电脑只剩C盘了
- 圆的半径java_计算圆的半径
- Tryhackme-Web Hacking Fundamentals
- 2018/10/25 模拟赛 纸牌
- vue 路由跳转 外部链接
- 3大类6种排序 插入排序 选择排序 冒泡排序 希尔排序 堆排序 快速排序 —————— 开开开山怪
- 阅读笔记-微表情心理学
- iOS开发者 如何突破自身技术瓶颈,成为别人眼中的 架构师?
热门文章
- Zabbix 使用微信接收报警信息
- Java语言程序设计(一)填空题
- 如何卸载windows自带的输入法
- 使用eclipse启动服务时,程序的发布目录
- 苹果审核之遇到IPV6问题被拒的解决方法
- 解决go get下载包失败问题
- 多重共线性的解决方法之——岭回归与LASSO
- 【部署问题】解决Nginx: [error] open() "/usr/local/Nginx/logs/Nginx.pid“ failed(2:No such file or directory)
- 遍历Java中的列表的方法
- 如何在'纯'Swift中创建弱协议引用(不带@objc)