在使用Springboot
整合定時任務,發現當某個定時任務執行出現執行時間過長的狀況時會阻塞其餘定時任務的執行。spring
後續經過翻查Springboot
的文檔以及打印日誌(輸出當前線程信息)得知問題是因爲Springboot
默認使用只有1
個線程的單線程池處理定時任務。spring-boot
須要注意示例的Springboot
版本爲2.1.3.RELEASE
。線程
<!--繼承父項目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> ...省略非關鍵配置 <!-- 引入依賴--> <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> <scope>test</scope> </dependency> </dependencies>
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * 定時任務 * @author RJH * create at 2019-03-29 */ @Component public class SimpleTask { private static Logger logger= LoggerFactory.getLogger(SimpleTask.class); /** * 執行會超時的任務,定時任務間隔爲5000ms(等價於5s) */ @Scheduled(fixedRate = 5000) public void overtimeTask(){ try { logger.info("current run by overtimeTask"); //休眠時間爲執行間隔的2倍 Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 正常的定時任務 */ @Scheduled(fixedRate = 5000) public void simpleTask(){ logger.info("current run by simpleTask"); } }
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling public class TaskDemoApplication { public static void main(String[] args) { SpringApplication.run(TaskDemoApplication.class, args); } }
...省略非關鍵信息 2019-03-29 21:22:38.410 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by simpleTask 2019-03-29 21:22:38.413 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by overtimeTask 2019-03-29 21:22:48.413 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by simpleTask 2019-03-29 21:22:48.414 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by overtimeTask 2019-03-29 21:22:58.418 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by simpleTask 2019-03-29 21:22:58.418 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by overtimeTask 2019-03-29 21:23:08.424 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by simpleTask 2019-03-29 21:23:08.424 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by overtimeTask 2019-03-29 21:23:18.425 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by simpleTask 2019-03-29 21:23:18.426 INFO 59731 --- [ scheduling-1] com.rjh.task.SimpleTask : current run by overtimeTask ...
由運行結果能夠看出:日誌
scheduling-1
這個線程處理simpleTask
被overtimeTask
阻塞致使了運行間隔變成了10
秒後面經過查閱Springboot
的文檔也得知了定時任務默認最大運行線程數爲1
。code
因爲使用的Springboot
版本爲2.1.3.RELEASE
,因此有兩種方法解決這個問題繼承
在配置文件中能夠配置定時任務可用的線程數:接口
## 配置可用線程數爲10 spring.task.scheduling.pool.size=10
使用自定義的線程池代替默認的線程池ci
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; /** * 定時任務配置類 * @author RJH * create at 2019-03-29 */ @Configuration public class ScheduleConfig { /** * 此處方法名爲Bean的名字,方法名無需固定 * 由於是按TaskScheduler接口自動注入 * @return */ @Bean public TaskScheduler taskScheduler(){ // Spring提供的定時任務線程池類 ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler(); //設定最大可用的線程數目 taskScheduler.setPoolSize(10); return taskScheduler; } }