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


猜你喜欢
- java中synchronized(同步代码块和同步方法)详解及区别问题的由来:看到这样一个面试题://下列两个方法有什么区别p
- 示例代码如下:namespace SampleListT{ class Program { &
- 本文实例讲述了Android开发之SD卡文件操作。分享给大家供大家参考,具体如下:前面的文章中写过直接操作手机自带存储器的程序,这次就接着上
- 首先来个效果图 布局文件代码在布局文件中,CoordinatorLayout作为布局文件根节点,AppBarLayo
- 前言Java项目开发中经常要用到分页功能,现在普遍使用SpringBoot进行快速开发,而数据层主要整合SpringDataJPA和MyBa
- 下标到指针之间和转换以下的程序做了什么。#include <stdio.h> int main() { int a
- pom.xml与settings.xmlpom.xml与setting.xml,可以说是Maven中最重要的两个配置文件,决定了Maven的
- BroadcastReceiver(广播 * ),在Android开发中,BroadcastReceiver的应用场景非常多,属于Andro
- 闭锁相当于一扇门,在闭锁到达结束状态之前,这扇门一直是关闭着的,没有任何线程可以通过,当到达结束状态时,这扇门才会打开并容许所有线程通过。它
- 大家好,我是程序员田同学!今天上午收到一个需求,针对当前的系统开发一个对外开放的接口。既然是对外开放,那么调用者一定没有我们系统的Token
- C# 和 java 比较:java 中使用的是接口。C# 使用委托机制,可以用时 + 运算符进行注册,直接多播。而 java 中是一般是使用
- 定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。设计初衷:
- mybatis-plus自动配置mapper.xml与java接口映射本来没有mybatis-plus的话,这个工作是通过mybatis-s
- Java单例模式的实现,对java 单例模式的几种实现方法进行了整理:单例模式好多书上都是这么写的:public class SingleT
- 本文实例为大家分享了Android自动播放Banner图片轮播的具体代码,供大家参考,具体内容如下先看一下效果图支持本地图片以及网络图片or
- 在HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(
- 为什么要用synchronized相信大家对于这个问题一定都有自己的答案,这里我还是要啰嗦一下,我们来看下面这段车站售票的代码:/** *
- 运行环境windows 7下载地址环境下载最近开接触Android(安卓)嵌入式开发,首要问题是搭建Andoid开发环境,由于本人用的是wi
- 前言 短时间提升自己最快的手段就是背面试题,最近总结了Java常用的面试题,分享给大家,希望大家都能圆梦大厂,加油,我命由我不由天
- dynamic是C#里面的动态类型,可在未知类型的情况访问对应的属性,非常灵活和方便。使用Json.Net可以把一个Json字符串转换成一个