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

作者:思灵月 时间:2021-06-06 08:41:27 

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

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


<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,依赖相关包:


<dependency>
       <groupId>org.quartz-scheduler</groupId>
       <artifactId>quartz</artifactId>
       <version>2.2.1</version>
</dependency>

定时任务配置如下:


<!-- 工作的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


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。

依赖包


<dependency>
       <groupId>org.quartz-scheduler</groupId>
       <artifactId>quartz</artifactId>
       <version>2.2.1</version>
</dependency>

配置:


<!-- 工作的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,定时任务,停止
0
投稿

猜你喜欢

  • Java中的static关键字深入理解

    2022-02-01 12:59:40
  • 详解Spring全局异常处理的三种方式

    2023-11-11 15:31:47
  • java实现用户自动登录

    2023-11-10 14:38:59
  • C# 位图BitArray的使用

    2022-09-13 23:54:46
  • Spring创建Bean的6种方式详解

    2022-07-18 19:10:13
  • SpringBoot日志框架之Log4j2快速入门与参数详解

    2023-11-15 21:17:59
  • Spring Boot 日志配置方法(超详细)

    2021-09-06 19:08:52
  • Java汉字转拼音工具类完整代码实例

    2021-07-09 21:32:18
  • Spring Boot + Vue 前后端分离项目如何踢掉已登录用户

    2021-07-23 21:57:35
  • 并行Stream与Spring事务相遇会发生什么?

    2022-08-28 15:40:12
  • java异常与错误处理基本知识

    2023-11-25 10:44:59
  • C#自定义控件实现TextBox禁止粘贴的方法

    2023-08-03 06:00:22
  • Java 继承与多态的深入理解

    2023-10-05 04:25:41
  • 详解Java中clone的写法

    2023-09-08 17:00:43
  • C#动态执行批处理命令的方法

    2023-03-16 23:19:40
  • C# 图片格式转换的实例代码

    2023-03-11 13:32:46
  • Android中aapt命令实践

    2021-10-26 08:57:45
  • prometheus监控springboot应用简单使用介绍详解

    2023-02-24 03:49:00
  • c#基于winform制作音乐播放器

    2023-08-06 11:55:08
  • Android 处理OnItemClickListener时关于焦点颜色的设置问题

    2021-09-02 01:47:00
  • asp之家 软件编程 m.aspxhome.com