在平常的業務開發過程當中,可能會須要實現一些週期性定時任務,好比定時同步數據庫、定時發送短信 或者 郵件等。java
那麼在 Java 中,共有三種定時任務的實現方式:spring
經過 java.util.Timer、TimerTask 實現。數據庫
經過 Spring 自帶的 SpringTask。(Spring 3.0 之後)springboot
經過 Spring 結合 Quartz 實現。異步
而本文說的是第二種方式 - Spring 定時器。線程
如今開發都是基於 springboot,而在 springboot 中配置 spring task 尤其簡單。code
步驟以下:blog
準備一個 springboot 工程ci
在啓動類上添加 @EnableScheduling 註解開發
@SpringBootApplication @EnableScheduling public class DemoApplication { }
在定時執行的方法上添加 @Scheduled(fixedDelay = 3 * 1000) 註解
@Scheduled(fixedDelay = 3 *1 000) public void p1(){ System.out.println(Thread.currentThread().getName() + " p1"); }
注意: 第三步註解的屬性會在後面細講
@Scheduled 註解
在說註解屬性以前, 須要瞭解下 Spring 定時器的三種工做模式。
1. fixedDelay
當上一次的任務執行完成以後, 再等 3 秒鐘, 執行下一次任務。
示意圖以下:
配置以下:
@Scheduled(fixedDelay = 3 * 1000)
2. fixedRate
會根據設置的值, 來預計每次任務應該在何時執行。
假定設置的值是 3 秒。那麼每一個任務預計執行的時間就是 3 秒鐘, 定時任務在 7點 0分 0秒 開始執行。
示意圖以下:
配置以下:
@Scheduled(fixedRate = 3 * 1000)
3. cron
假定設置的每 5 秒 執行一次,會每隔 5 秒來看一下,上一個任務是否執行完成。
示意圖以下:
配置以下:
@Scheduled(cron = "0/3 * * * * ? ")
問題
瞭解了 Spring 定時器的三種工做模式後,來思考一個問題,以下面時序圖的定時功能?
答案
默認狀況下,定時任務是由一個單線程執行的。因此咱們須要定義一個線程池去異步執行定時任務。
具體步驟:
定義一個線程池
@Configuration @EnableAsync public class SchedulerAsyncConfig { @Bean public Executor taskExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setMaxPoolSize(200); executor.setCorePoolSize(10); executor.setQueueCapacity(10); executor.initialize(); return executor; } }
在定時任務上加上 @Async 註解。
@Scheduled(fixedDelay = 10) @Async public void p1(){ System.out.println(Thread.currentThread().getName() + " p1"); }