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定时任务 >>>>>>>>>>>> ...
随机推荐
- Java中的单实例
前几天刚学完单实例设计模式,今天看代码时发现一行代码很奇怪,getRuntime()函数的返回类型怎么是它本身,忽然想起前几天学的单实例模式,于是找到方法的定义,果然是静态私有变量,获取实例的公有方法 ...
- java环境变量---找不到或无法加载主类
默认安装在C:\ProgramFiles\Java\jdk1.7.0目录下 环境变量配置为 PATH=.;%JAVA_HOME%\bin CLASSPATH=.;%JAVA_HOME%\lib\dt. ...
- 力扣(LeetCode)191. 位1的个数
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量). 示例 1: 输入:00000000000000000000000000001011 输出:3 ...
- 小程序for循环给里面单独的view加单独的样式
效果图如下: 上面是个列表从数据库拿下来所有的信息:在视图层直接一个for循环展示下来,现在麻烦来了前三个和后面的额不一样,小程序不允许dom操作,那怎么解决呢? 解决办法: wx:for和wx:if ...
- linux yum+wget详解
在做自动化测试的时候,有个test需要执行命令:wget http://www.aliyun.com,但是返回的结果是未找到命令wget,于是百度了相关资料,发现没有安装wget,于是利用yum in ...
- Bash Shell 注释多行的几种方法(转)
很实用的小技巧. 我们shell脚本写好了,但是想一行一行测试,怎么办. 笨方法:每行前面加一个 #,有时候我们原脚本里面本来就有注释,所以想再恢复的时候就麻烦了. Bash Shell 注释多行的几 ...
- 使用getCurrentPosition方法实时获取当前Geolocation信息(附源码文件)--html5、JavaScript
使用getCurrentPosition方法实时获取当前Geolocation信息: 1.getCurrentPosition方法的使用 navigator.geolocation.getCurren ...
- Confluence 6 归档一个空间
当你认为一个空间不再需要实时进行编辑,但你还希望在后面某个时候能够对空间重新进行访问编辑的时候,你可以对空间进行归档.归档一个空间,这样你可以让你归档的空间让最少的人能看见,但是你的空间还是可以在 C ...
- python基础之函数参数,名称空间,以及函数嵌套
函数进阶内容梗概: 1. 函数参数--动态传参 2. 名称空间, 局部名称空间, 全局名称空间, 作⽤用域, 加载顺序. 3. 函数的嵌套 4. gloabal , nonlocal 关键字 1. 函 ...
- CF数据结构练习
1. CF 438D The Child and Sequence 大意: n元素序列, m个操作: 1,询问区间和. 2,区间对m取模. 3,单点修改 维护最大值, 取模时暴力对所有>m的数取 ...