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

