Spring定時任務(wù)無故停止又不報(bào)錯的解決
Spring定時任務(wù)無故停止又不報(bào)錯
一開始是使用Spring自帶的定時器來配置定時任務(wù)的,簡單快捷,配置如下:
<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>
但是使用一段時間之后就無故停止,且不報(bào)錯,所以沒有相關(guān)錯誤日志,需要重啟Tomcat之后才能繼續(xù)執(zhí)行定時任務(wù)。
開始以為由于數(shù)據(jù)庫最大連接數(shù)的限制,設(shè)置成翻倍了之后仍出現(xiàn)這問題。在同學(xué)的提醒下意識到可能是線程阻塞導(dǎo)致,于是網(wǎng)上查到原因:
Spring定時任務(wù)默認(rèn)都是并發(fā)執(zhí)行的,不會等待上一次任務(wù)執(zhí)行完畢,只要間隔時間到就會執(zhí)行。
解決方案
1.將JobDetail的concurrent屬性配置為false。不允許任務(wù)并發(fā)執(zhí)行。
2.任務(wù)執(zhí)行時間較長時,查找根本問題。
于是把Spring自帶的定時器改用Quartz,依賴相關(guān)包:
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
定時任務(wù)配置如下:
<!-- 工作的bean -->
<bean id="myJob" class=" com.gionee.baserom.exchangerate.job.DailyTaskJob" />
<!-- 定義任務(wù),為了避免線程阻塞,用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>
<!-- 配置觸發(fā)器 -->
<bean id="myJobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="myJobDetail" />
<property name="cronExpression" value="0 0/30 * * * ?" />
</bean>
<!-- 配置調(diào)度器 -->
<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是因?yàn)楫?dāng)Tomcat被關(guān)閉時,有可能導(dǎo)致任務(wù)線程并未完全關(guān)閉,導(dǎo)致內(nèi)存泄漏。
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定時任務(wù)跑完不再啟動
spring的定時任務(wù)有以下兩個特性
1、單定時任務(wù)之間是串行,之前的任務(wù)沒執(zhí)行完,下一個任務(wù)不會啟動。
2、多個任務(wù)之間會相互干擾,其他同一時刻啟動的任務(wù)沒執(zhí)行完,下一個任務(wù)不會啟動。
排查方式
1、首先檢查自己的代碼,是否有死鎖、卡住、bug、http請求沒有設(shè)置超時時間等問題。
2、檢查是否所有定時任務(wù)都不啟動,如果是基本判斷是特性2導(dǎo)致的,檢查是哪個定時任務(wù)執(zhí)行慢、卡住、出現(xiàn)bug等情況。
解決思路
1、修復(fù)bug,如果有的話。
2、如果就是有個任務(wù)執(zhí)行慢,無法優(yōu)化,可以不用spring的定時任務(wù),改用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" />
<!-- 定義任務(wù),為了避免線程阻塞,用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>
<!-- 配置觸發(fā)器 -->
<bean id="myJobTrigger"
class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="myJobDetail" />
<property name="cronExpression" value="0 0/30 * * * ?" />
</bean>
<!-- 配置調(diào)度器 -->
<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>
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot實(shí)現(xiàn)文件壓縮處理詳解
在工作我們經(jīng)常會出現(xiàn)有多個文件,為了節(jié)省資源會將多個文件放在一起進(jìn)行壓縮處理,本文將使用SpringBoot實(shí)現(xiàn)文件壓縮處理,感興趣的可以了解下2024-11-11
如何在Maven項(xiàng)目中運(yùn)行JUnit5測試用例實(shí)現(xiàn)
這篇文章主要介紹了如何在Maven項(xiàng)目中運(yùn)行JUnit5測試用例實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
Java中ArrayIndexOutOfBoundsException 異常報(bào)錯的解決方案
本文主要介紹了Java中ArrayIndexOutOfBoundsException 異常報(bào)錯的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06

