Spring Task/Spring Scheduler 傻傻分不清
首先做一下“名詞解釋”,分清楚這兩者的區別:
Spring Task
- Spring Task 是 Spring 框架自帶的一個任務調度模塊,提供了基本的任務調度功能。
- 它是通過 Java 的 Timer 和 TimerTask 類來實現的,這兩個類提供了一種簡單的方式來安排和執行重復性任務。
- Spring Task 可以通過
@Scheduled
注解將方法標記為定時任務,并指定任務的觸發條件、執行時間間隔等屬性。 - Spring Task 適用于簡單的定時任務和重復性任務,但在處理復雜任務、并發任務或需要更高級功能的場景下有限。
Spring Scheduler
Spring Scheduler 也稱為 Spring Scheduling。
- Spring Scheduling 是 Spring 框架對任務調度的一種增強支持,建立在 Spring Task 基礎上。
- 它使用了一個更強大、靈活且可擴展的任務調度器接口,例如
TaskScheduler
和ThreadPoolTaskScheduler
。 - Spring Scheduling 提供了比 Spring Task 更多的特性和配置選項,如異步執行任務、并發控制、任務取消和動態調度等。
- 它還提供了更多的任務觸發選項和靈活的表達式語法,例如 Cron 表達式。
總結起來,Spring Task 是 Spring 框架自帶的一個簡單任務調度模塊,提供了基本的定時任務功能;而 Spring Scheduling 是對任務調度的增強支持,提供了更多特性和配置選項,適用于更復雜的任務調度需求。如果您只需要簡單的定時任務,可以使用 Spring Task;如果需要更豐富的任務調度功能,可以選擇 Spring Scheduling。
本組件簡介
大家都知道 Spring Scheduler 好用和怎么用,但它沒有一個像 XXL-Job 有個后臺界面的,好像不太完整,于是筆者打算為 Spring Scheduler 提供一個可視化的操作界面,雖然趕不上 XXL-Job 那么強大,但也算彌補其中缺失的一環。它支持在線監控執行的任務、支持動態修改任務狀態、暫停/恢復任務,以及終止運行中任務。
另外本組件的特色就是非常簡單,或者說“輕量級”,只有兩個主要的類和一個前端靜態 html 組成,Java 的話總共不超過 500 行代碼。
核心原理
我們先進入原理層面談談(如果讀者覺得太難可以先略過)。
- 核心
ScheduleHandler
類,連完整的注釋才 160 行。其作用如下:- 主要圍繞 Spring 核心原理,從加載機制中得到哪些是定時器的方法,收集起來以便統一管理
- 如何對任務控制呢?通過
ScheduledTask
和ScheduledFuture
,可以擴展實現動態修改任務狀態、暫停/恢復任務,以及終止運行中任務。ScheduledTask 表示所有被@Scheduled
注解修飾的任務 - 如何得到 ScheduledTask 對象呢?這就涉及 Spring 加載機制了。眾所周知,Spring 是一個開放系統,暴露了大量開放的接口供用戶使用。其中原理我們不妨看看
ScheduleHandler
源碼就知道。
- 控制器
ScheduledController
,這是提供 API 接口的。任務可以得到了,可是怎么對其管理呢?我們很自然地想到用數據庫來進行 CRUD 的管理,但問題又來了,Spring 任務連個名稱或者 id 都沒有,怎么做數據庫管理呢?筆者想了下,就是通過類名稱和執行方法組成唯一的條件,就是一個獨特的任務記錄,可以進行入庫和管理。這個類除了調用上述的 Spring ScheduledTask API 外,還有涉及的數據庫的 CRUD 操作。其中一個怎么停止任務的地方,比較巧妙地說。 - 前端 task.html,如下圖所示,非常簡單,
就一個 HTML,僅僅依賴 vue.js(CDN 加載),而且 js/css 全在 HTML 里面,都是原生手寫的,直接雙擊瀏覽器打開即可使用(當然你接口前提必須是跨域的)。非常方便你整合。
后端依賴的話,是我的框架AJAXJS,當然是非常輕量級的,連 MyBatis 都沒依賴。如果你不打算依賴 AJAXJS,把這兩個類摳出來也是非常簡單的。
另外,該組件在 Spring MVC 5 下調試通過,無須 Spring Boot 亦可。
源碼在:https://gitee.com/sp42_admin/ajaxjs/tree/master/aj-backend/aj-framework/aj-framework/src/main/java/com/ajaxjs/framework/spring/scheduled。
使用配置
Spring 工程配置如下:
// 初始化 Spring 任務調度器
@Bean
public ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();pool.setCorePoolSize(5); // 指定線程數pool.setMaxPoolSize(10);pool.setWaitForTasksToCompleteOnShutdown(true);return pool;
}// 初始化任務調度管理
@Bean(initMethod = "init")
public ScheduleHandler scheduleHandler() {return new ScheduleHandler();
}// 注入任務調度的控制器
@Bean
public ScheduledController scheduledController() {return new ScheduledController();
}
前端頁面源碼在這里。你要簡單修改下接口地址什么的。
使用限制
對于固定頻率的,fixedRate,因為不能獲取其類和方法,故不能加入到任務管理中
//每隔2秒執行一次
@Scheduled(fixedRate = 2000)
public void testTasks() {System.out.println("定時任務執行時間:" + dateFormat.format(new Date()));
}
但幸運地,可以轉化為 Cron 表達式的,
@Scheduled(cron = "0/2 * * * * *") // cron 表達式,每5秒執行
public void doTask() {System.out.println("我是定時任務~" + ATOMIC_LONG.getAndIncrement());
}
參考
- 從零搭建開發腳手架 基于Spring Task實現動態管理任務 和本文一個思想,但它的好像對 Task 包了一層,顯得有點復雜。不過考慮到高并發的設計
- Spring Boot Task 定時任務升級(啟動、停止、變更執行周期) 說原理的
- @Scheduled定時任務管理界面 本組件就是從它啟發的!——大幅度重構
- Schedule 調度系統設計(單機版) 可惜看不到源碼了
- 輕量級分布式任務調度框架 Light Task Schedule 這個其實很龐大跟復雜,看看就好
- 在線Cron表達式生成器
- SandGlass 是一款為 java 設計的分布式任務調度工具
其他同類的界面參考: