定时任务Quartz和spring task


这两个在多数情况下可以替换,所以都不怎么注意两者的区别,前段时间遇到了一个问题,使用Spring task,莫名其妙的不执行job了,Log下了日志,看了一下,发现停止在了一个耗时操作上(不会结束,等待响应状态),之前一直没有问题,于是就对比了一下代码的版本,发现了区别:

1、tomcat启动改成了SpringBoot

2、quartz改成了Springtask

第一个是容器的变动,一般不会有问题

第二个值得怀疑,

于是查看了org.springframework.scheduling.quartz.SchedulerFactoryBean这个源码,发现是多线程的,而Springtask默认是单线程

所以在任务没有结束的时候Springtask继续等待,而quartz另起线程执行,

于是解决的办法就出来了:

解决方法1:如下配置pool-size,但这样会导致同一个task前一个还没跑完后面又被触发的问题。

<task:scheduler id="scheduler" pool-size="2" />

解决方法2:让任务分别运行在不同的scheduler里就好了,这样每个job独立运行,不会因为一个job堵塞而停止运行

<task:scheduler id="myScheduler1"/>
<task:scheduler id="myScheduler2"/>
<task:scheduled-tasks scheduler="myScheduler1">
<task:scheduled ref="doSomethingTask" method="doSomething" cron="${0 * * * * *}"/>
</task:scheduled-tasks>
<task:scheduled-tasks scheduler="myScheduler2">
<task:scheduled ref="doOtherThingTask" method="doOtherThing" cron="${0 * * * * *}"/>
</task:scheduled-tasks>

解决方法3:使用quartz,遇到堵塞,另起线程处理

解决方法4:另添加线程池,然job在线程池中运运行

综合起来无非就是一个:多线程。基本保证了每一个job独立,准时运行。

这里又有几个典型问题

1、为什么不全部默认多线程,Springtask单线程有何意义?

可以保证一段时间内job只执行一次,避免执行冲突与重复操作

2、可以时间设置长一点,就不会有执行冲突与重复操作了?

有的job是为了保证数据的即时性的,时间不可以设置太长

所以选用哪种定时任务,还是要看具体的业务场景的,结合业务场景才可以完美解决问题。


附:

  1. 每隔指定时间则触发一次,在Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean
  2. 每到指定时间则触发一次,在Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean

CronTriggerBean自带线程

经验分享 程序员 微信小程序 职场和发展