spring定时器任务多任务串行执行问题排查

原文:https://www.cnblogs.com/youtianhong/p/6027249.html

最近发现个生产问题,定时器任务某些任务没有及时执行。经过研究排查发现spring 定时器任务scheduled-tasks默认配置是单线程串行执行的,这就造成了若某个任务执行时间过长,其他任务一直在排队,业务逻辑没有及时处理的问题。

如下是scheduled定义了3个任务。

<task:scheduled-tasks >
  <task:scheduled ref="myTask1" method="run" cron="0 0/59 10-23 * * ?"/>
  <task:scheduled ref="myTask2" method="run" cron="0/10 * * * * ?"/>
  <task:scheduled ref="myTask3" method="run" cron="0/10 * * * * ?"/>
</task:scheduled-tasks>

查看该任务17点的执行日志(task名字已修改)

zgrep -e ‘2016-10-28 17:‘ channel-task.log.2016-10-28.log.gz | grep -e ‘MyTask2‘

2016-10-28 17:14:25,002 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> [email protected]
2016-10-28 17:14:35,980 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task [email protected]
2016-10-28 17:14:40,002 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> [email protected]
2016-10-28 17:14:50,681 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task [email protected]
2016-10-28 17:14:55,003 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> [email protected]
2016-10-28 17:15:05,613 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task [email protected]

2016-10-28 17:20:35,246 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> [email protected]
2016-10-28 17:20:46,051 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task [email protected]

2016-10-28 17:20:50,003 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] start task >> [email protected]
2016-10-28 17:21:00,974 INFO [pool-8-thread-1 - ] task.AbstractTask - [TASK] complete task [email protected]

MyTask2每10秒钟执行一次,但是在17:15:05 到17:20:35之间,5分钟内定时任务没有执行

执行命令 zgrep -e ‘2016-10-28 17:1‘ task.log.2016-10-28.log.gz  (当天17点10几分发生的日志)

然后在查询日志发现,这5分钟之内有大量的日志在执行

2016-10-28 17:17:20,202 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893418 ] 
2016-10-28 17:17:20,477 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893401 ] 
2016-10-28 17:17:20,731 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280893402 ] 
.........中间省略n条日志

2016-10-28 17:19:59,752 INFO [pool-8-thread-1 - ] task.MyTask3 - compare query order[ 211621610280894049 ]

通过过以上日志可以看出,该线程[pool-8-thread-1 - ] 一直在处理MyTask3任务,此时断定 task:scheduled 配置默认是单线程串行的,

网上查找资料发现如下配置可以解决问题

<task:scheduler id="scheduler" pool-size="3" />
<task:scheduled-tasks scheduler="scheduler" >
  <task:scheduled ref="myTask1" method="run" cron="0 0/59 11-23 * * ?"/>
  <task:scheduled ref="myTask2" method="run" cron="0/10 * * * * ?"/>
  <task:scheduled ref="myTask3" method="run" cron="0/10 * * * * ?"/>
</task:scheduled-tasks>

如果是注解的方式

@Scheduled(cron = "0 0/1 * * * ?")

那就在applicationContext.xml文件加入<task:scheduler id="scheduler" pool-size="2" />这一行,pool-size表示线程的个数

或者是下面的这一种方式

1.简单单任务定时器的spring配置

<!-- 配置定时任务,用于初始化定时器 -->  
    <bean id="InitJobDetail"  
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
        <property name="targetObject">  
            <ref bean="ReportJobTodo"/>  
        </property>  
        <property name="targetMethod">  
            <value>initJobTrigger</value>  
        </property>  
        <property name="concurrent" value ="false"/>    
    </bean>  
    <bean id="ReportJobTodo"  
        class="cn.com.gsoft.report.timetask.ReportJobTodo">  
    </bean>  
    <bean id="InitTrigger"  
        class="org.springframework.scheduling.quartz.CronTriggerBean">  
        <property name="jobDetail">  
            <ref bean="InitJobDetail"/>  
        </property>  
        <property name="cronExpression">  
            <value>* * * * * ?</value>  
        </property>  
    </bean>  
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
        <property name="triggers">  
            <list>  
                <ref local="InitTrigger"/>  
            </list>  
        </property>  
    </bean>  
<!-- 配置定时任务,用于初始化定时器 -->
 <bean id="InitJobDetail"
  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
  <property name="targetObject">
   <ref bean="ReportJobTodo"/>
  </property>
  <property name="targetMethod">
   <value>initJobTrigger</value>
  </property>
     <property name="concurrent" value ="false"/> 
 </bean>
 <bean id="ReportJobTodo"
  class="cn.com.gsoft.report.timetask.ReportJobTodo">
 </bean>
 <bean id="InitTrigger"
  class="org.springframework.scheduling.quartz.CronTriggerBean">
  <property name="jobDetail">
   <ref bean="InitJobDetail"/>
  </property>
  <property name="cronExpression">
   <value>* * * * * ?</value>
  </property>
 </bean>
 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <property name="triggers">
   <list>
    <ref local="InitTrigger"/>
   </list>
  </property>
 </bean>

说明:(1).InitJobDetail实例声明了需要执行的任务。其中targetObject说明了需要执行的方法所在的实例对象,targetMethod说明了要执行的方法,concurrent用于说明多个任务是否同步执行。

(2).InitTrigger声明了一个触发器。jobDetail属性指明需要执行的任务,cronExpression声明了该任务在什么时候执行,该表达式跟linux下的crontab定时程序中使用的表达式是一样的,具体使用方法可以参考文后的参考资料。

(3).SchedulerFactoryBean中可以定义多个触发器,以实现多任务。

原文地址:https://www.cnblogs.com/shihaiming/p/8447132.html

时间: 2024-10-04 00:58:04

spring定时器任务多任务串行执行问题排查的相关文章

loadrunner多场景的串行执行以及定时执行

方法一: 既然是脚本串行执行,那在场景设计中必然是要用多个脚本,要注意的是需要将Scenario Schedule中的Schedule by设置为Group的模式.然后按实际需要依次设置每个脚本的Schedule.要事先计算好每个脚本的整个执行时间,方便定义后续脚本的开始时间(设置Start Group). 方法二: 使用定时任务执行: 首先创建并设置好要跑的个测试场景,再创建一个一个批处理程序按先后顺序调用这几个个场景进行测试,最后通过Windows的定时任务设定批处理的执行时间 写一个批处理

关于异步任务串行执行的思考与实现

最近在做的一个需求被产品的各种奇葩要求和各种为了体验的迷之借口搞得面目前非,里面有很多异步请求,而且有时候是独立执行,有时候需要相互依赖的串行执行(A的结果回来了,成功的话执行B,不成功不管).一开始我都是非常简单的在Activity中实现各种回调接口,然后在回调方法中调用下一个异步请求,为了能串行的执行,因此加了很多boolean值标记当前什么状态.然后我就想做一个可以封装异步任务,然后按照顺序异步执行的一个模式. 我希望使用的时候,可以new一个AsyncTask对象,然后它成功的后执行什么

oracle中并行执行不一定比串行执行快

并行执行与串行执行相比,能否缩短执行时间,取决于如下几个方面:1.待执行的目标SQL是否适合并行执行,有些SQL是不太适合并行执行的,比如走索引的嵌套循环连接.2.数据库服务器上的硬件资源(如CPU.内存.I/O等)是否还有富余.3.并行执行时,是否最大化地利用了数据库服务器上的硬件资源(但同时又不能使数据库服务器上的硬件资源消耗殆尽).4.待执行的目标SQL的并行执行计划是否为当前情形下的最优执行计划. 原文地址:https://www.cnblogs.com/qinjf/p/8414654.

背水一战 Windows 10 (118) - 后台任务: 后台下载任务(任务分组,并行或串行执行,组完成后通知)

[源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下载任务(任务分组,并行或串行执行,组完成后通知) 示例演示后台下载任务的分组,以及如何设置组内任务是并行执行还是串行执行,以及组任务全部完成后如何 toast 或 tile 通知)BackgroundTask/TransferModel.cs /* * 扩展了 DownloadOperation 和 UploadOperation,用于 MVVM 绑定数据 */ using System; using S

spring定时任务(scheduler)的串行、并行执行

对于spring的定时任务,最近有接触过一些,对于串行和并行也学习了一下,现在这里做下记录. 我是把每个定时任务分别写在不同的类中的,即一个类就是一个定时任务,然后在spring配置文件中进行配置,首先说串行任务的配置.如下: 1.串行 <task:scheduled-tasks> <task:scheduled ref="className1" method="methodName1" cron="0 0/5 * * * ?"

并行执行、串行执行和并发执行

并发执行是多道程序系统中多个程序(逻辑上互相独立)或者一个程序中的多个程序段在执行的过程当中,时间互相重叠,一个程序执行没结束,另一个已经开始. 并行执行是指一组程序按照独立的,不同步的速度执行,时间上不重叠: 串行就是指令一个一个的执行.并行是指令同时并行执行. 总结: 并发是指多个线程轮流执行(单核CPU): 并行是指多个线程同时执行(多核CPU),微观上是同时的: 串行是指一个一个的执行,处理完一个才能处理下一个,不轮换: 原文地址:https://www.cnblogs.com/feix

ThreadPoolTaskExecutor 多线程分解执行耗时任务与单线程串行执行简单比较

import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.T

【iOS面试系列-2】多线程中同步、异步和串行、并行之间的逻辑关系(必考,必须掌握)

一.同步.异步和串行.并行 任务串行执行就是每次只有一个任务被执行,任务并发执行就是在同一时间可以有多个任务被执行. 一个同步函数只在完成了它预定的任务后才返回.一个异步函数,刚好相反,会立即返回,预定的任务会完成但不会等它完成.因此,一个异步函数不会阻塞当前线程去执行下一个函数. (来源:http://www.cocoachina.com/industry/20140428/8248.html) 队列分为串行和并行 任务的执行分为同步和异步 -------  队列只是负责任务的调度,而不负责任

十天学会单片机Day4串行口通信

并行与串行基本通信方式 1.并行通信方式 通常是将数据字节的各位用多条数据线同时进行传送. 并行通信控制简单.传输速度快:由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难. 2.串行通信方式 是将数据字节分成一位一位的形式在一条传输线上逐个地传送. 串行通信传输线少,长距离传送时成本低,且可以利用电话网等现成的设备,但数据的传送控制比并行通信复杂. 3.异步串行通信方式 异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程.为使双方的收发协调,要求发送和接收设备