spring boot默認單執行緒排隊跑定時任務問題記錄

  • 2019 年 12 月 15 日
  • 筆記

作者:小小明童鞋

鏈接:https://my.oschina.net/xiaomingnevermind/blog/3143095

問題描述:在使用springboot默認的定時任務時,若存在多個任務,框架默認只啟動一個執行緒執行,會導致有些任務不能在指定時間開始執行

另,關於分散式下定時任務同步鎖問題,會再單獨寫一篇記錄

測試默認情況下定時任務的執行緒名稱:

package com.example.demo.job;    import net.javacrumbs.shedlock.core.SchedulerLock;  import org.springframework.scheduling.annotation.EnableScheduling;  import org.springframework.scheduling.annotation.Scheduled;  import org.springframework.stereotype.Component;    import java.time.LocalDateTime;    @Component  @EnableScheduling  public class TestJob {          @Scheduled(cron = "0/5 * * * * ?")      @SchedulerLock(name = "test1-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")      public void execute1() {          String curName = Thread.currentThread().getName();          System.out.println("當前時間:" + LocalDateTime.now() + "  任務execute1對應的執行緒名: " + curName);          try {              Thread.sleep(1000);          } catch (Exception e) {              e.printStackTrace();          }        }        @Scheduled(cron = "0/5 * * * * ?")      @SchedulerLock(name = "test2-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")      public void execute2() {            String curName = Thread.currentThread().getName();          System.out.println("當前時間:" + LocalDateTime.now() + "  任務execute2對應的執行緒名: " + curName);          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }      }        @Scheduled(cron = "0/10 * * * * ?")      @SchedulerLock(name = "test3-task", lockAtMostForString = "PT28M", lockAtLeastForString = "PT28M")      public void execute3() {            String curName = Thread.currentThread().getName();          System.out.println("當前時間:" + LocalDateTime.now() + "  任務execute3對應的執行緒名: " + curName);          try {              Thread.sleep(1000);          } catch (InterruptedException e) {              e.printStackTrace();          }      }    }

結果如下:

spring boot 自帶的定時任務默認只起一個執行緒:

這種情況下,對於有些定時任務若設定在某一固定時刻開始執行,就可能出現需要排隊而不能準時執行的情況。然後找了下解決方案,我不太想巴拉源碼了,網上大家都扒出來了,就是為空初始化一個執行緒那段,直接點上解決方案:

在啟動類裡面加上如下程式碼:

/**  	 *  解決定時任務單執行緒排隊問題,建立執行緒池  	 * @return  	 */  	@Bean  	public TaskScheduler taskScheduler() {  		ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();  		taskScheduler.initialize();  		taskScheduler.setPoolSize(50);  		return taskScheduler;  	}

然後重新啟動看下執行緒的情況:

以及核心執行緒數:

這樣就解決了單執行緒問題。

另:分散式情況下只能有一個定時任務在執行,防止重複執行的方案有很多,下次再寫。