springBoot已經默認集成了定時任務的依賴,只須要引入基本的依賴就可使用定時任務。java
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-parent</artifactId> <version>2.0.0.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
在啓動類中須要加入@EnableScheduling註解,意思是開啓定時任務。spring
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; /** * Author: YaoQi * Date: 2018/9/28 21:37 * Description: springBoot schedule */ @SpringBootApplication @EnableScheduling public class ScheduleApp { public static void main(String[] args) { SpringApplication.run(ScheduleApp.class, args); } }
寫一個定時任務demo,每秒種打印一第二天志,並打印當前時間驗證當前任務執行週期。多線程
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; /** * Author: YaoQi * Date: 2018/9/28 21:40 * Description: Scheduled Task */ @Service public class ScheduleTask { private static final Logger logger = LoggerFactory.getLogger(ScheduleTask.class); @Scheduled(cron = "*/1 * * * * ?") public void execute() { logger.info("print word."); logger.info(String.valueOf(System.currentTimeMillis())); } }
運行結果:ide
從上圖的結果中看:該任務基本是每秒種執行一次,若是不手動中止,程序會一直執行下去,而且從日誌中看,這個任務的執行週期是1s左右,恰好和設置的cron表達式一致;而且執行這個任務的線程一直是poll-1-thread-1這個線程。這就意味着,這個定時任務啓動是由單獨的一個線程去執行的。spring-boot
這時候,可能會有幾個問題:ui
若是任務執行的時間比執行週期要短,這個任務會怎麼執行?線程
若是有多個任務執行,還會是一個線程去執行這個任務嗎?日誌
首先驗證第一個問題,當任務執行的時間比執行週期短時,任務的執行狀況。code
@Scheduled(cron = "*/1 * * * * ?") public void execute() { logger.info("print word."); logger.info(String.valueOf(System.currentTimeMillis())); try { Thread.sleep(6000L); } catch (InterruptedException e) { e.printStackTrace(); } }
執行結果:每次任務的執行時間間隔爲7秒,而且是同一個線程在執行。xml
若是有多個任務執行,任務的執行狀況。
@Scheduled(cron = "*/1 * * * * ?") public void execute() { logger.info("print word."); try { Thread.sleep(6000L); } catch (InterruptedException e) { e.printStackTrace(); } } @Scheduled(cron = "*/1 * * * * ?") public void execute1() { logger.info(String.valueOf(System.currentTimeMillis())); logger.info("write message."); }
執行結果:
執行結果:第二個每秒執行一次的任務的並無安裝設定的執行週期執行,運行結果並無達到預期。而且兩個任務都是由同一個線程去運行。
示例分析中問題2的緣由就是執行多個任務並非多個線程執行,致使執行第一個任務時,第二個任務進入等待狀態。springBoot中提供了多線程運行定時任務的方式。
@Configuration public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3)); } }
增長一個配置類,設置線程池,並設置線程池大小,這裏的線程池大小就仁者見仁了,和你程序中的任務的個數有關係,也和機器的核數有關係。
經過配置線程池就能讓每一個任務獨立執行,不受其餘任務的影響,由於是在不一樣的線程中執行的,但若是涉及到公共資源就另當別論了。
執行結果:
上述中的執行週期都是以cron表達式定義的,這種方式最靈活,可是上文中的表達式都寫到代碼中去了,不便於修改,這裏提供一種配置方式,直接用表達式獲取yml中的配置信息。
scheduleTask: cron1: "*/1 * * * * ?" cron2: "*/1 * * * * ?"
在yml中添加cron的配置信息。而後在Java註解中能夠直接獲取。
@Scheduled(cron = "${scheduleTask.cron2}") public void execute1() { logger.info(String.valueOf(System.currentTimeMillis())); logger.info("write message."); }