在咱們如今的項目中,或多或少的都會涉及到定時任務,Spring在3.0以後引入了SpringSchedule,這讓咱們在使用Spring的時候,能夠很容易的整合SpringSchedule.可是好用歸好用,用的時候仍是有一些點注意的.java
SpringSchedule 中提供的定時任務,默認是單線程執行的,也就是說若是任務較多,或者某一個任務執行耗時比較久,那麼顯然易見,會很容易致使其他任務排隊以及阻塞..net
既然存在這種問題,那麼怎麼去避免這種問題?這時候你們很容易想到的就是使用線程池,多個線程去跑定時任務.沒錯,正確的解決方案就是配置線程池.線程
之因此默認是單線程執行的,是由於當咱們沒有配置taskSchedule的時候,默認建立的是一個單線程的線程池。具體代碼解析參考:https://blog.csdn.net/weixin_40318210/article/details/78149692日誌
先看一下沒配置線程池的狀況下的任務執行線程日誌:orm
定時任務業務類的代碼以下:blog
@Component public class TaskConfig { private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); @Scheduled(fixedDelayString = "5000") //單機 public void getTask1() throws InterruptedException { //競爭鎖邏輯代碼 ..... System.out.println("任務1,當前時間:" + dateFormat.format(new Date())+",線程號:"+Thread.currentThread().getName()); //throw new RuntimeException("xxxxx"); Thread.sleep(10000); } @Scheduled(cron = "0/5 * * * * ?") public void getTask2() { System.out.println("任務2,當前時間:" + dateFormat.format(new Date())+",線程號:"+Thread.currentThread().getName()); } }
任務執行日誌爲:get
能夠看到執行這兩個任務的線程老是同一個線程.io
那麼咱們如今加入線程池的配置,配置代碼以下:form
@Configuration public class ScheduleConfig implements SchedulingConfigurer { public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskExecutor()); } //配置線程池---觸發器和任務共用的 @Bean(destroyMethod="shutdown") public Executor taskExecutor() { return Executors.newScheduledThreadPool(10); } }
接下來咱們再觀察一下定時任務的執行信息:class
如今看到是加入線程池後,每次執行的定時任務的線程在不斷的變化,同時這兩個任務也能夠並行的執行,能夠避免任務的阻塞與排隊.
若是你的代碼中使用了SpringSchedule,並且尚未使用線程池,那麼趕忙去修改吧.