Java后臺(tái)定時(shí)器導(dǎo)致系統(tǒng)崩潰的原因和解決方法
一、常見定時(shí)器類型
| 定時(shí)器類型 | 特點(diǎn) | 風(fēng)險(xiǎn)點(diǎn) |
|---|---|---|
@Scheduled(Spring) | 簡(jiǎn)單、固定間隔 | 單線程、阻塞整個(gè)調(diào)度器 |
| ScheduledExecutorService | 可配置線程池 | 線程池耗盡 |
| XXL-JOB、ElasticJob | 分布式調(diào)度 | 調(diào)度過(guò)頻/單機(jī)壓力大 |
自寫 Timer | 單線程 | 異常導(dǎo)致整個(gè) Timer 線程退出 |
許多崩潰問(wèn)題和這些機(jī)制有關(guān)。
二、系統(tǒng)崩潰的常見根因(按頻率排序)
1. 定時(shí)任務(wù)阻塞/卡死(最常見)
場(chǎng)景舉例:
你用 @Scheduled(fixedRate=5000),任務(wù)執(zhí)行需要 30 秒。
問(wèn)題:
- Spring 的
ScheduledAnnotationBeanPostProcessor默認(rèn)是 單線程執(zhí)行器 - 上一次任務(wù)還沒結(jié)束,下一次又來(lái)
- 排隊(duì)越來(lái)越長(zhǎng)
- CPU 占用飆升
- 最終線程卡死或 OOM
@EnableScheduling
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar registrar) {
registrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
2. 定時(shí)任務(wù)拋異常導(dǎo)致線程退出
如果使用 Timer:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
int a = 1 / 0; // 異常
}
}, 0, 1000);
結(jié)果:
- Timer 線程會(huì)完全退出
- 之后所有任務(wù)都不再執(zhí)行
- 某些關(guān)鍵操作失效 → 系統(tǒng)異常甚至宕機(jī)
3. 任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng)導(dǎo)致資源積壓
例如:
- 定時(shí)任務(wù)掃描數(shù)據(jù)庫(kù) 50W 條記錄
- 每分鐘執(zhí)行一次
- 查詢/鎖造成數(shù)據(jù)庫(kù)壓力過(guò)大
- 系統(tǒng)數(shù)據(jù)庫(kù)連接耗盡
- 業(yè)務(wù)接口全掛
真實(shí)案例:
“定時(shí)對(duì)賬任務(wù)”每 10 分鐘執(zhí)行,執(zhí)行一次需要 12 分鐘,后來(lái)數(shù)據(jù)庫(kù)基本 100% CPU,業(yè)務(wù)查詢都 timeout。
4. 任務(wù)中出現(xiàn)死循環(huán) / 無(wú)限重試
while (true) {
// MQ 超時(shí)就 retry
}
結(jié)果:
- CPU 100%
- 內(nèi)存不斷增加
- 最終 OOM 直接導(dǎo)致系統(tǒng)崩潰
5. 定時(shí)任務(wù)并發(fā)執(zhí)行無(wú)鎖,導(dǎo)致 DB 互相死鎖
update table1 set status=1 where status=0;
任務(wù) B 同時(shí)執(zhí)行同一邏輯 → 死鎖概率大增,導(dǎo)致:
- MySQL 大量鎖等待
- 1205 鎖等待超時(shí)
- 線程池阻塞
- 系統(tǒng)吞吐量驟降
- 最終接口超時(shí)、服務(wù)假死
6. 任務(wù)日志大量輸出導(dǎo)致磁盤寫滿
[INFO] task running...
大量日志文件導(dǎo)致:
/var/log或容器磁盤寫滿- 應(yīng)用無(wú)法寫日志 → 報(bào)錯(cuò)
- MySQL 也可能無(wú)法寫入 binlog → 崩潰
7. 定時(shí)任務(wù)里使用了阻塞 IO(HTTP、Redis、MQ 等)
如果第三方 API 超時(shí),任務(wù)一直卡著,直接阻塞定時(shí)線程,導(dǎo)致:
- 定時(shí)任務(wù)全卡住
- 所有任務(wù)執(zhí)行延遲
- 如果線程池只有 1 個(gè),全部任務(wù)失效
8. 定時(shí)任務(wù)內(nèi)存泄漏
特別是你常寫類似:
List<Object> cache = new ArrayList<>();
放在靜態(tài)變量中,每次執(zhí)行都 append,不清理。
長(zhǎng)期運(yùn)行 → 堆積 → OOM → 服務(wù)崩潰
三、常見“定時(shí)器導(dǎo)致系統(tǒng)崩潰”的真實(shí)場(chǎng)景總結(jié)
| 場(chǎng)景 | 后果 |
|---|---|
| 定時(shí)任務(wù)讀取大量數(shù)據(jù) | 數(shù)據(jù)庫(kù)壓力爆炸 |
| 多個(gè)任務(wù)同時(shí)掃描數(shù)據(jù)庫(kù) | 死鎖 + 慢 SQL |
| 任務(wù)執(zhí)行時(shí)間 > 調(diào)度間隔 | 任務(wù)排隊(duì),線程池耗盡 |
| 一個(gè)異常導(dǎo)致整個(gè)定時(shí)器退出 | 關(guān)鍵任務(wù)不再執(zhí)行,系統(tǒng)雪崩 |
| 日志打印過(guò)多寫滿磁盤 | 服務(wù)無(wú)法寫日志 → 崩潰 |
| 定時(shí)任務(wù)中線程未關(guān)閉 | 線程數(shù)爆增,系統(tǒng)掛掉 |
到此這篇關(guān)于Java后臺(tái)定時(shí)器導(dǎo)致系統(tǒng)奔潰的原因和解決方法的文章就介紹到這了,更多相關(guān)Java后臺(tái)定時(shí)器導(dǎo)致系統(tǒng)奔潰內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring MVC集成springfox-swagger2構(gòu)建restful API的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring MVC集成springfox-swagger2構(gòu)建restful API的相關(guān)資料,文中介紹介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-06-06
淺談MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的
本文主要介紹了MySQL中是如何實(shí)現(xiàn)事務(wù)提交和回滾的,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
SpringBoot同一個(gè)方法操作多個(gè)數(shù)據(jù)源保證事務(wù)一致性
本文探討了在Spring Boot應(yīng)用中,如何在同一個(gè)方法中操作多個(gè)數(shù)據(jù)源并保證事務(wù)的一致性,由于聲明式事務(wù)的限制,直接使用@Transactional注解無(wú)法滿足需求,文章介紹了解決方案:編程式事務(wù),它允許在代碼級(jí)別更靈活地管理事務(wù),確保多數(shù)據(jù)源操作的事務(wù)一致性2024-11-11
跳表的由來(lái)及Java實(shí)現(xiàn)詳解
跳表(Skip List)是一種基于鏈表的數(shù)據(jù)結(jié)構(gòu),它可以支持快速的查找、插入、刪除操作,本文主要來(lái)和大家講講跳表的由來(lái)與實(shí)現(xiàn),感興趣的小伙伴可以了解一下2023-06-06
IDEA中設(shè)置代碼自動(dòng)提示為Alt+/的具體做法
很多公司都強(qiáng)制性要求使用Intellij?IDEA,其實(shí)Intellij?IDEA也確實(shí)很好用,但是一下子從Eclipse跳轉(zhuǎn)到Intellij?IDEA轉(zhuǎn)也是需要一段時(shí)間的,為了迎合之前的習(xí)慣,就需要在Intellij?IDEA中改變一些設(shè)置,如代碼自動(dòng)生成,本文給大家分享設(shè)置方法,感興趣的朋友一起看看吧2023-01-01
Springboot使用token防止重復(fù)提交表單問(wèn)題
文章主要描述了一個(gè)關(guān)于用戶登錄測(cè)試的過(guò)程,涉及到了DuplicateSubmitToken、DuplicateSubmitExceptionTextConstants和DuplicateSubmitAspect等術(shù)語(yǔ),這些可能是在測(cè)試過(guò)程中用于防止重復(fù)提交的功能或注解2026-05-05
@Autowired自動(dòng)裝配接口時(shí)存在多個(gè)實(shí)現(xiàn)的處理過(guò)程
文章介紹了在Spring中@Autowired自動(dòng)裝配接口如果存在多個(gè)實(shí)現(xiàn)類時(shí)的注入問(wèn)題,建議通過(guò)@Resource或@Qualifier注解按名稱指定注入,避免編譯報(bào)錯(cuò),并分享了個(gè)人實(shí)踐經(jīng)驗(yàn)2025-10-10
簡(jiǎn)單操作實(shí)現(xiàn)Java jsp servlet文件上傳過(guò)程解析
這篇文章主要介紹了簡(jiǎn)單操作實(shí)現(xiàn)Java jsp servlet文件上傳過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
深入學(xué)習(xí)SpringCloud之SpringCloud簡(jiǎn)介
Spring Cloud是一個(gè)一站式的開發(fā)分布式系統(tǒng)的框架,為開發(fā)者提供了一系列的構(gòu)建分布式系統(tǒng)的工具集,本文給大家介紹springcloud的相關(guān)知識(shí),感興趣的朋友跟隨一起看看吧2021-04-04

