好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring定时任务无故停止又不报错的解决

Spring定时任务无故停止又不报错

一开始是使用Spring自带的定时器来配置定时任务的,简单快捷,配置如下:

?

1

2

3

4

< bean id = "refreshCache" class = "com.gionee.baserom.search.job.RefreshCache" />

< task:scheduled-tasks >

     < task:scheduled ref = "refreshCache" method = "execute" cron = "0 */30 * * * ?" />

</ task:scheduled-tasks >

但是使用一段时间之后就无故停止,且不报错,所以没有相关错误日志,需要重启Tomcat之后才能继续执行定时任务。

开始以为由于数据库最大连接数的限制,设置成翻倍了之后仍出现这问题。在同学的提醒下意识到可能是线程阻塞导致,于是网上查到原因:

Spring定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行。

解决方案

1.将JobDetail的concurrent属性配置为false。不允许任务并发执行。

2.任务执行时间较长时,查找根本问题。

于是把Spring自带的定时器改用Quartz,依赖相关包:

?

1

2

3

4

5

< dependency >

         < groupId >org.quartz-scheduler</ groupId >

         < artifactId >quartz</ artifactId >

         < version >2.2.1</ version >

</ dependency >

定时任务配置如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

<!-- 工作的bean -->

     < bean id = "myJob" class = " com.gionee.baserom.exchangerate.job.DailyTaskJob" />

     <!-- 定义任务,为了避免线程阻塞,用concurrent=false -->

     < bean id = "myJobDetail"

         class = "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" >

         < property name = "targetObject" ref = "myJob" />

         < property name = "targetMethod" value = "execute" />

         < property name = "concurrent" value = "false" />

     </ bean >

     <!-- 配置触发器  -->

     < bean id = "myJobTrigger"

         class = "org.springframework.scheduling.quartz.CronTriggerFactoryBean" >

         < property name = "jobDetail" ref = "myJobDetail" />

         < property name = "cronExpression" value = "0 0/30 * * * ?" />

     </ bean >

     <!-- 配置调度器 -->

     < bean name = "startQuertz" lazy-init = "false" autowire = "no" destroy-method = "destroy"

         class = "com.gionee.baserom.exchangerate.util.SchedulerFactoryBeanWithShutdownDelay" >

         < property name = "quartzProperties" >

             < props >

                 < prop key = "org.quartz.threadPool.threadCount" >1</ prop >

             </ props >

         </ property >

         < property name = "waitForJobsToCompleteOnShutdown" >

             < value >false</ value >

         </ property >

         < property name = "triggers" >

             < list >

                 < ref bean = "myJobTrigger" />

             </ list >

         </ property >

     </ bean >

在startQuartz中用到SchedulerFactoryBeanWithShutdownDelay是因为当Tomcat被关闭时,有可能导致任务线程并未完全关闭,导致内存泄漏。

SchedulerFactoryBeanWithShutdownDelay.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

import org.quartz.SchedulerException;

import org.springframework.scheduling.quartz.SchedulerFactoryBean;

public class SchedulerFactoryBeanWithShutdownDelay extends SchedulerFactoryBean {

     @Override

     public void destroy() throws SchedulerException { 

         super .destroy(); 

         try { 

             Thread.sleep( 1000 ); 

         } catch (InterruptedException e) { 

             throw new RuntimeException(e); 

         } 

     } 

}

Spring定时任务跑完不再启动

spring的定时任务有以下两个特性

1、单定时任务之间是串行,之前的任务没执行完,下一个任务不会启动。

2、多个任务之间会相互干扰,其他同一时刻启动的任务没执行完,下一个任务不会启动。

排查方式

1、首先检查自己的代码,是否有死锁、卡住、bug、http请求没有设置超时时间等问题。

2、检查是否所有定时任务都不启动,如果是基本判断是特性2导致的,检查是哪个定时任务执行慢、卡住、出现bug等情况。

解决思路

1、修复bug,如果有的话。

2、如果就是有个任务执行慢,无法优化,可以不用spring的定时任务,改用Quartz。

依赖包

?

1

2

3

4

5

< dependency >

         < groupId >org.quartz-scheduler</ groupId >

         < artifactId >quartz</ artifactId >

         < version >2.2.1</ version >

</ dependency >

配置:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

<!-- 工作的bean -->

     < bean id = "myJob" class = " com.gionee.baserom.exchangerate.job.DailyTaskJob" />

 

     <!-- 定义任务,为了避免线程阻塞,用concurrent=false -->

     < bean id = "myJobDetail"

         class = "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" >

         < property name = "targetObject" ref = "myJob" />

         < property name = "targetMethod" value = "execute" />

         < property name = "concurrent" value = "false" />

     </ bean >

 

     <!-- 配置触发器  -->

     < bean id = "myJobTrigger"

         class = "org.springframework.scheduling.quartz.CronTriggerFactoryBean" >

         < property name = "jobDetail" ref = "myJobDetail" />

         < property name = "cronExpression" value = "0 0/30 * * * ?" />

     </ bean >

 

     <!-- 配置调度器 -->

     < bean name = "startQuertz" lazy-init = "false" autowire = "no" destroy-method = "destroy"

         class = "com.gionee.baserom.exchangerate.util.SchedulerFactoryBeanWithShutdownDelay" >

         < property name = "quartzProperties" >

             < props >

                 < prop key = "org.quartz.threadPool.threadCount" >1</ prop >

             </ props >

         </ property >

         < property name = "waitForJobsToCompleteOnShutdown" >

             < value >false</ value >

         </ property >

         < property name = "triggers" >

             < list >

                 < ref bean = "myJobTrigger" />

             </ list >

         </ property >

     </ bean >

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/bcqtt/article/details/52471113

查看更多关于Spring定时任务无故停止又不报错的解决的详细内容...

  阅读:35次