Spring @Scheduled @Async联合实现调度任务(2017.11.28更新)
定时任务之前一直用的是quartz之类,但是注意到Spring中其实也提供了一种简单的调度注释@Scheduled,也就想尝一下鲜..
代码示意如下:
@Component
@EnableScheduling
public class AsyncTaskHandlerTask { @Scheduled(fixedDelay = 1000)
public void task1() {
//输出日志
} @Scheduled(fixedDelay = 1000)
public void task2() {
//输出日志
}
}
执行了一下,完全ok,日志打印正常,2个任务也都正常定时执行了.那好,添加些业务逻辑进去:
@Component
@EnableScheduling
public class AsyncTaskHandlerTask { @Scheduled(fixedDelay = 1000)
public void task1() {
while(true){
....
}
} @Scheduled(fixedDelay = 1000)
public void task2() {
while(true){
....
}
} }
再启动,咦,奇怪了,怎么定时任务没有执行呢?倘使我之前没有输出日志试验,我可能就认为注解的用法错了呢...重新添加日志,下断点重跟了一下启动过程发现:
程序进入到while死循环后就卡死了,没有再继续启动另一个定时任务了.通过现象可知@Scheduled启动过程是一个单线程同步启动过程,故一旦中途被阻塞,会导致整个启动过程阻塞,
其余的定时任务都不会启动.这明显很奇怪,网上的教程大多数是xml配置形式,Spring的官网我这头打开又奇慢无比..但是从xml的配置形式可知需要配置一个线程池来启动定时任
务.但是Javaconfig形式的则没有说明.但是我查询到了另一个注解@Async,这个异步注解我是使用过的,可以指定线程池,打到方法上后便会以指定的线程池来执行方法.然后解决方案来了:
@Component
@EnableScheduling
public class AsyncTaskHandlerTask { @Scheduled(fixedDelay = 1000)
@Async
public void task1() {
while(true){
....
}
} @Scheduled(fixedDelay = 1000)
@Async
public void task2() {
while(true){
....
}
} }
再次启动,不会再被阻塞.
2017-11-28更新:
本来以为找到了正解,结果证明是误入了歧途..以上是完全错误的使用,虽然看起来貌似是正确的..正应了一句话啊,啥都不如看源码啊...
太懒了,本来这个应该再单独开个文章再说的,但是太懒了...
进入正题,按照如上实现部署后突然发现一个诡异的问题,定时任务发生了异常的"阻塞"现象,某个任务突然看起来不再执行了,直接卡死了.第一印象是死锁了,直接jstack生成了一份堆栈信息,仔细分析后发现一个诡异问题,定时任务并没有像Scheduled定义的那样一次结束后再执行下一次,而是并发执行多次,直接将Async定义的线程池跑满.那么问题也就好解释了,Async注解后,直接异步在新线程中执行任务,由于异步执行Scheduled认为上一次已经执行完马上开始执行下一次,导致不停执行定时任务直接跑满Async使用的线程池.那么这实际上是一种错误的使用方法..怎么办?
只好点了@EnableScheduling注解看一下源码中怎么说的吧.
* <p>When more control is desired, a {@code @Configuration} class may implement
* {@link SchedulingConfigurer}. This allows access to the underlying
* {@link ScheduledTaskRegistrar} instance. For example, the following example
* demonstrates how to customize the {@link Executor} used to execute scheduled
* tasks:
实际上已经说的很明白了,更多的控制,只需要继承 SchedulingConfigurer 这个类,之前没有找到对应xml中配置线程池的方法也正是如此.
* public class AppConfig implements SchedulingConfigurer {
*
* @Override
* public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
* taskRegistrar.setScheduler(taskExecutor());
* }
*
* @Bean(destroyMethod="shutdown")
* public Executor taskExecutor() {
* return Executors.newScheduledThreadPool(100);
* }
* }
标红处就是使用线程池的配置,之后再执行不仅以多线程来启动定时任务,而且也不会出现定时任务重复并发执行的问题.至此此问题圆满解决.再感叹下啥都不如看源码.
Spring @Scheduled @Async联合实现调度任务(2017.11.28更新)的更多相关文章
- Xamarin 2017.11.9更新
Xamarin 2017.11.9更新 本次更新主要针对Xamarin.iOS,适配了iOS 11.1和Xcode 9.1.Visual Studio 2017升级到15.4.3获得新功能.Visu ...
- Xamarin 2017.11.1更新
Xamarin 2017.11.1更新 本次更新主要解决了一些bug.Visual Studio 2017升级到15.4.2获得新功能.Visual Studio 2015需要工具-选项-Xamar ...
- 2017.11.28 Enginering management:problem-solving ability
Today,my colleague is on bussiness trip. going to customer factory in jiangxi. slove the color diffe ...
- Spring Boot @Async 异步任务执行
1.任务执行和调度 Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象. Spring的TaskExecutor和java.util.concurre ...
- Spring @Scheduled Annotation
1.Overview 这里我们将会学习Spring @Scheduled 标签,了解它是如何配置,如何设置定时任务. 关于它的使用,有两点简单的规则需要记住: ※它的方法应该是一个void返回值类型 ...
- 定时任务 spring @Scheduled注解
使用spring @Scheduled注解执行定时任务: 运行!!! 关于Cron表达式(转载) 表达式网站生成: http://cron.qqe2.com/ 直接点击 cronExpression ...
- Spring @Scheduled应用解析
最近,遇到的一个需求,需要执行定时任务,每个一定时间需要执行某个方法 因为项目是SpringMVC的项目,所以使用的是Spring @Scheduled(由于quartz应用起来太麻烦,所以没有采用) ...
- 使用轻量级Spring @Scheduled注解执行定时任务
WEB项目中需要加入一个定时执行任务,可以使用Quartz来实现,由于项目就一个定时任务,所以想简单点,不用去配置那些Quartz的配置文件,所以就采用了Spring @Scheduled注解来实现了 ...
- spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务
spring计划任务,springMvc计划任务,Spring@Scheduled,spring定时任务 >>>>>>>>>>>> ...
随机推荐
- python 下载大文件
当使用requests的get下载大文件/数据时,建议使用使用stream模式. 当把get函数的stream参数设置成False时,它会立即开始下载文件并放到内存中,如果文件过大,有可能导致内存不足 ...
- cp命令覆盖文件时不用按Y来确认的方法
我们在Linux下使用cp命令复制文件时候,有时候会需要覆盖一些同名文件,覆盖文件的时候都会有提示:需要不停的按Y来确定执行覆盖.文件数量不多还好,但是要是几百个估计按Y都要吐血了,于是折腾来半天总结 ...
- ip啊
网络模型被OSI分成七层,TCP/IP协议大致对应了2.3.4.7层,分别是数据链路层.网络层.传输层.应用层,IP协议处于网络层上,它的工作原理说白了并不复杂: 整个互联网上所有的机器都有唯一一个I ...
- Codeforces 1009 F - Dominant Indices
F - Dominant Indices 思路:树上启发式合并 先跑轻子树,然后清除轻子树的信息 最后跑重子树,不清除信息 然后再跑一遍轻子树,重新加回轻子树的信息 由于一个节点到根节点最多有logn ...
- ionic日历插件
1:引入插件的两个文件 timePicker.js 和timePicker.css文件 2:填加插件模块到项目模块中CorderYuan->app.js的moudule 3:在 ...
- python Scrapy 常见问题记录
ImportError: No module named win32api 处理办法 windows系统上出现这个问题的解决需要安装Py32Win模块,但是直接通过官网链接装exe会出现几百个错误,更 ...
- Day3-scrapy爬虫下载图片自定义名称
学习Scrapy过程中发现用Scrapy下载图片时,总是以他们的URL的SHA1 hash值为文件名,如: 图片URL:http://www.example.com/image.jpg 它的SHA1 ...
- (转)UCOSII在任务切换与出入中断时堆栈指针的使用
1 uc/os ii在M3中的堆栈结构 1.1 M3入账序列 1.2 加上手工入栈序列 2 PendSV在Cortex-M3中的应用 Systick为嵌入到内核中,优先级比一般中断优先级高.若在一 ...
- 数据结构(C语言版)-C语言和C++相关补充
引用类型作形参的三点说明 (1)传递引用给函数与传递指针的效果是一样的,形参变化实参也发生变化.(2)引用类型作形参,在内存中并没有产生实参的副本,它直接对实参操作:而一般变量作参数,形参与实参就占用 ...
- HTML 第十三章总结
前言 这一章的内容主要是处理 HTML 中的 tabular data,可以分为三个部分: 如何在 HTML 中创建表格 如何在 CSS 中 style 表格 如何在 CSS 中 style HTML ...