Spring定時任務(wù)無故停止又不報錯
一開始是使用Spring自帶的定時器來配置定時任務(wù)的,簡單快捷,配置如下:
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 > |
但是使用一段時間之后就無故停止,且不報錯,所以沒有相關(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)包:
1
2
3
4
5
|
< dependency > < groupId >org.quartz-scheduler</ groupId > < artifactId >quartz</ artifactId > < version >2.2.1</ version > </ dependency > |
定時任務(wù)配置如下:
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" /> <!-- 定義任務(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是因為當(dāng)Tomcat被關(guān)閉時,有可能導(dǎo)致任務(wù)線程并未完全關(guān)閉,導(dǎo)致內(nèi)存泄漏。
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定時任務(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。
依賴包
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" /> <!-- 定義任務(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)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/bcqtt/article/details/52471113