spring boot默認單執行緒排隊跑定時任務問題記錄
- 2019 年 12 月 15 日
- 筆記
作者:小小明童鞋
鏈接:https://my.oschina.net/xiaomingnevermind/blog/3143095
問題描述:在使用springboot默認的定時任務時,若存在多個任務,框架默認只啟動一個執行緒執行,會導致有些任務不能在指定時間開始執行
另,關於分散式下定時任務同步鎖問題,會再單獨寫一篇記錄
測試默認情況下定時任務的執行緒名稱:
package com.example.demo.job; import net.javacrumbs.shedlock.core.SchedulerLock; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.time.LocalDateTime; @Component @EnableScheduling public class TestJob { @Scheduled(cron = "0/5 * * * * ?") @SchedulerLock(name = "test1-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M") public void execute1() { String curName = Thread.currentThread().getName(); System.out.println("當前時間:" + LocalDateTime.now() + " 任務execute1對應的執行緒名: " + curName); try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } @Scheduled(cron = "0/5 * * * * ?") @SchedulerLock(name = "test2-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M") public void execute2() { String curName = Thread.currentThread().getName(); System.out.println("當前時間:" + LocalDateTime.now() + " 任務execute2對應的執行緒名: " + curName); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } @Scheduled(cron = "0/10 * * * * ?") @SchedulerLock(name = "test3-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M") public void execute3() { String curName = Thread.currentThread().getName(); System.out.println("當前時間:" + LocalDateTime.now() + " 任務execute3對應的執行緒名: " + curName); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
結果如下:

spring boot 自帶的定時任務默認只起一個執行緒:

這種情況下,對於有些定時任務若設定在某一固定時刻開始執行,就可能出現需要排隊而不能準時執行的情況。然後找了下解決方案,我不太想巴拉源碼了,網上大家都扒出來了,就是為空初始化一個執行緒那段,直接點上解決方案:
在啟動類裡面加上如下程式碼:
/** * 解決定時任務單執行緒排隊問題,建立執行緒池 * @return */ @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); taskScheduler.initialize(); taskScheduler.setPoolSize(50); return taskScheduler; }
然後重新啟動看下執行緒的情況:

以及核心執行緒數:

這樣就解決了單執行緒問題。
另:分散式情況下只能有一個定時任務在執行,防止重複執行的方案有很多,下次再寫。

