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定时任务 >>>>>>>>>>>> ...
随机推荐
- hibernate的三种状态和缓存
hibernate的三种状态: 1.瞬时态:对象里面没有id值,对象与session没有关联 类似,把class类new出来,不存进session 2.持久态:对象里面有id值,对象与session关 ...
- fileInputStream.available()获取 文件的总大小
available():返回与之关联的文件的字节数 我们用inputStream.available()获取 文件的总大小
- x1c 6th usb-c 接口灯常亮,电源无法充电
症状: 左侧能充电的那个usb-c 红灯始终常亮.拔下电源线也亮着. 系统里电源是始终显示正在充电,即使拔掉外接电源也显示连着外接电源正在充电! ——最吓人的是,用U盘启动进PE,想重装win10,结 ...
- EasyUI datebox 设置不可编辑后再次修改为可编辑失效的解决
工作中遇到的问题,折腾了好久: 如下图: 需求:当状态发生改变后,如果状态是未核实 , 核实人 核实时间 核实结果 核实说明 均为不可编辑状态 具体js代码如下: //状态改变 $('#js ...
- lua --- dofile、loadfile、require
loadfile: 1>编译代码成中间码并且返回编译后的chunk作为一个函数,而不执行代码 2>在发生错误的情况下,不会抛出异常,但会返回nil和错误信息 3>运行一个文件多次的话 ...
- 第一个dubbo程序
Dubbo是一个高性能服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,使得应用可通过高性能RPC实现服务的输出和输入功能,和Spring框架可以无缝集成. 作为一个 ...
- python+kafka,从指定位置消费数据
# @staticmethoddef get_kafka_reviews(self): # print type(self.bootstrap_servers) consumer = kafka.Ka ...
- <山月记>:中岛敦 -选段
因为害怕自己并非明珠而不敢刻苦琢磨,又因为有几分相信自己是明珠,而不能与瓦砾碌碌为伍,遂逐渐远离世间,疏避人群,结果在内心不断地用愤懑和羞怒饲育着自己懦弱的自尊心.世上每个人都是驯兽师,而那匹猛兽,就 ...
- 【文献04】无人驾驶高速AWID-AWIS车辆运动控制研究
参考:阮久宏, 李贻斌, 荣学文, et al. 无人驾驶高速AWID-AWIS车辆运动控制研究[J]. 农业机械学报, 2009, 40(12):37-42. https://drive.wps.c ...
- Getting Started with Processing 第四章总结
为什么要使用变量: 我们使用变量的一个重要原因就是避免变成过程中的重复工作,如果你重复使用某一个数字超过了一次,就可以考虑使用一个变量来代替它,这样你的程序会更加通用并且易于更新. 定义变量 定义变量 ...