溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring定時(shí)任務(wù)無(wú)故停止又不報(bào)錯(cuò)怎么辦

發(fā)布時(shí)間:2021-11-02 11:42:17 來(lái)源:億速云 閱讀:425 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Spring定時(shí)任務(wù)無(wú)故停止又不報(bào)錯(cuò)怎么辦的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

Spring定時(shí)任務(wù)無(wú)故停止又不報(bào)錯(cuò)

一開(kāi)始是使用Spring自帶的定時(shí)器來(lái)配置定時(shí)任務(wù)的,簡(jiǎn)單快捷,配置如下:

<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>

但是使用一段時(shí)間之后就無(wú)故停止,且不報(bào)錯(cuò),所以沒(méi)有相關(guān)錯(cuò)誤日志,需要重啟Tomcat之后才能繼續(xù)執(zhí)行定時(shí)任務(wù)。

開(kāi)始以為由于數(shù)據(jù)庫(kù)最大連接數(shù)的限制,設(shè)置成翻倍了之后仍出現(xiàn)這問(wèn)題。在同學(xué)的提醒下意識(shí)到可能是線程阻塞導(dǎo)致,于是網(wǎng)上查到原因:

Spring定時(shí)任務(wù)默認(rèn)都是并發(fā)執(zhí)行的,不會(huì)等待上一次任務(wù)執(zhí)行完畢,只要間隔時(shí)間到就會(huì)執(zhí)行。

解決方案

1.將JobDetail的concurrent屬性配置為false。不允許任務(wù)并發(fā)執(zhí)行。

2.任務(wù)執(zhí)行時(shí)間較長(zhǎng)時(shí),查找根本問(wèn)題。

于是把Spring自帶的定時(shí)器改用Quartz,依賴相關(guān)包:

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

定時(shí)任務(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)閉時(shí),有可能導(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定時(shí)任務(wù)跑完不再啟動(dòng)

spring的定時(shí)任務(wù)有以下兩個(gè)特性

1、單定時(shí)任務(wù)之間是串行,之前的任務(wù)沒(méi)執(zhí)行完,下一個(gè)任務(wù)不會(huì)啟動(dòng)。

2、多個(gè)任務(wù)之間會(huì)相互干擾,其他同一時(shí)刻啟動(dòng)的任務(wù)沒(méi)執(zhí)行完,下一個(gè)任務(wù)不會(huì)啟動(dòng)。

排查方式

1、首先檢查自己的代碼,是否有死鎖、卡住、bug、http請(qǐng)求沒(méi)有設(shè)置超時(shí)時(shí)間等問(wèn)題。

2、檢查是否所有定時(shí)任務(wù)都不啟動(dòng),如果是基本判斷是特性2導(dǎo)致的,檢查是哪個(gè)定時(shí)任務(wù)執(zhí)行慢、卡住、出現(xiàn)bug等情況。

解決思路

1、修復(fù)bug,如果有的話。

2、如果就是有個(gè)任務(wù)執(zhí)行慢,無(wú)法優(yōu)化,可以不用spring的定時(shí)任務(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>

感謝各位的閱讀!關(guān)于“Spring定時(shí)任務(wù)無(wú)故停止又不報(bào)錯(cuò)怎么辦”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI