排行榜排程,使用 @Scheduled 來建立項目,以秒或分為單位,定期執行任務, EP 25-1 增加了範例,並透過 Application 來驗證產出結果。
Table of Contents
Toggle前言
Leaderboard 排行榜統計玩家資訊,如:徽章,勝負場次,勝點,在遊戲中是一個常見的系統,主要圍繞著的滿足玩家競爭心所帶來的榮耀感,因此多久同步一次資料,就使用排程來實現。
Scheduling LeaderboardJob
檔案目錄
./
+- build.gradle
+- src
+- main
+- resources
| +- application.properties
+- java
+- org
+- ruoxue
+- spring_boot_168
+- job
| +- report
| +- leaderboard
| +- LeaderboardJob.java
設定
Scheduling Tasks
參考此篇:
application.properties
增加 Scheduling 設定。
scheduling.enable=true
@Scheduled 參數
Param | Description |
cron | 表示式,指定任務在特定時間執行 |
fixedDelay | 表示上一次任務執行完成後多久再次執行,參數型別 long ,單位毫秒 |
fixedDelayString | 與 fixedDelay 一樣功能,參數型別 String |
fixedRate | 表示按一定的頻率執行任務,參數型別 long ,單位毫秒 |
fixedRateString | 與 fixedRate 一樣功能,參數型別 String |
initialDelay | 表示延遲多久執行第一次任務,參數型別 long,單位毫秒 |
initialDelayString | 與 initialDelay 一樣功能,參數型別 String |
zone | 時區,預設為目前時區 |
Cron 表示式
Cron 是一個字串,是由空格隔開的 6 或 7 個域所組成,每一個域對應一個含義,如:秒 分 時 每月第幾天 月 星期 年,其中年是可選欄位。
┌───────────── second (0-59) │ ┌───────────── minute (0 - 59) │ │ ┌───────────── hour (0 - 23) │ │ │ ┌───────────── day of the month (1 - 31) │ │ │ │ ┌───────────── month (1 - 12) (or JAN-DEC) │ │ │ │ │ ┌───────────── day of the week (0 - 7) │ │ │ │ │ │ (0 or 7 is Sunday, or MON-SUN) │ │ │ │ │ │ * * * * * *
Param | Description |
秒 | , – * / 四個字元,有效範圍為 0-59 的整數 |
分 | , – * / 四個字元,有效範圍為 0-59 的整數 |
時 | , – * / 四個字元,有效範圍為 0-23 的整數 |
每月第幾天 | , – * / ? L W C 八個字元,有效範圍為 0-31 的整數 |
月 | , – * / 四個字元,有效範圍為 1-12 的整數或 JAN-DEC |
星期 | , – * / ? L C # 八個字元,有效範圍為 1-7 的整數或 SUN-SAT 兩個範圍,1 表示星期天,2 表示星期一, 依次類推 |
* | 表示匹配該域的任意值,比如在秒*,就表示每秒都會觸發事件 |
? | 只能用在每月第幾天和星期兩個域,表示不指定值,當 2 個子表示式其中之一被指定了值以後,為了避免衝突,需要將另一個子表示式的值設為 ? |
- | 表示範圍,例如在分域使用 5-20 ,表示從 5 分到 20 分鐘每分鐘觸發一次 |
/ | 表示起始時間開始觸發,然後每隔固定時間觸發一次,例如在分域使用5/20,則意味著5分,25分,45分,分別觸發一次 |
, | 表示列出列舉值。例如:在分域使用5,20,則意味著在5和20分時觸發一次 |
L | 表示最後,只能出現在星期和每月第幾天域,如果在星期域使用 1L,意味著在最後的一個星期日觸發 |
W | 表示有效工作日(週一到週五),只能出現在每月第幾日域,系統將在離指定日期的最近的有效工作日觸發事件,W 的最近尋找不會跨過月份 |
LW | 這兩個字元可以連用,表示在某個月最後一個工作日,即最後一個星期五 |
# | 用於確定每個月第幾個星期幾,只能出現在每月第幾天域,例如在 1#3,表示某月的第三個星期日 |
LeaderboardJob.java
新增檔案。
Scheduling Job Description
使用 @Scheduled 定義排程。
使用 @ConditionalOnProperty 設定開啟或關閉排程。
package org.ruoxue.spring_boot_168.job.report.leaderboard;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
@ConditionalOnProperty(name = "scheduling.enable", havingValue = "true")
public class LeaderboardJob {
@Scheduled(initialDelay = 3000, fixedRate = 3000)
public void secondBoard() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
log.info("secondBoard: " + sdf.format(new Date()));
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Scheduled(initialDelay = 3000, fixedRate = 60000)
public void minuteBoard() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
log.info("minuteBoard: " + sdf.format(new Date()));
}
}
測試
Application.main
在主程式點右鍵執行 Run As -> Java Application,查看 console 。
2022-06-23T21:02:15.146+0800 [SCHEDULE-T-2] INFO secondBoard:20 - secondBoard: 2022/06/23 09:02:15
2022-06-23T21:02:15.146+0800 [SCHEDULE-T-1] INFO minuteBoard:31 - minuteBoard: 2022/06/23 09:02:15
2022-06-23T21:02:25.146+0800 [SCHEDULE-T-3] INFO secondBoard:20 - secondBoard: 2022/06/23 09:02:25
2022-06-23T21:02:35.147+0800 [SCHEDULE-T-4] INFO secondBoard:20 - secondBoard: 2022/06/23 09:02:35
2022-06-23T21:02:45.148+0800 [SCHEDULE-T-1] INFO secondBoard:20 - secondBoard: 2022/06/23 09:02:45
2022-06-23T21:02:55.148+0800 [SCHEDULE-T-2] INFO secondBoard:20 - secondBoard: 2022/06/23 09:02:55
2022-06-23T21:03:05.148+0800 [SCHEDULE-T-2] INFO secondBoard:20 - secondBoard: 2022/06/23 09:03:05
2022-06-23T21:03:15.146+0800 [SCHEDULE-T-4] INFO minuteBoard:31 - minuteBoard: 2022/06/23 09:03:15
心得分享
Task Scheduler
增加了參數設定 scheduling.enable ,用來開啟或關閉排程執行,尤其當測試或團隊協作時,常常會多人共同維護專案,同時啟動 Server,此時關閉排程,可以避免發生任務互搶執行的情況。