首頁 > 軟體

@Schedule 如何解決定時任務推遲執行

2022-10-02 14:00:12

前言

SpringBoot 實現定時任務很簡單,只需要使用**@Scheduled**註解即可,但是該註解是實現的定時任務預設是單執行緒的,也就意味著多個定時任務執行時就可能導致執行緒堵塞,延緩定時任務的執行。

下面就一步一步來解決這個問題。

一、@Scheduled

1、程式碼

// 啟用定時任務
@EnableScheduling 
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
@Component
public class Task {
    Logger logger = LoggerFactory.getLogger(Task.class);
	// 每五秒執行一次
    @Scheduled(cron = "0/5 * * * * ?")
    public void taskTestA() throws InterruptedException {
        logger.info("A:");
        TimeUnit.SECONDS.sleep(20);
    }
  
    // 每十秒執行一次
    @Scheduled(cron = "0/10 * * * * ?")
    public void taskTestB() {
        logger.info("B:");
    }
}

2、結果

由圖可知,首先這兩個定時任務都是單執行緒的,但是當定時A執行了一次後,由於定時A中有個休眠20秒,然後執行定時任務B,所以執行緒A第二次執行在25秒後才執行,這就是由於@Scheduled定時任務是單執行緒,造成的執行緒堵塞,導致定時任務推遲執行。

二、@Scheduled + 設定執行緒池

1、程式碼

和前面@Scheduled 相比,僅僅增加了設定執行緒池

// 若不設定預設為單執行緒,這裡設定使用執行緒池,大小為4
spring:
  task:
    scheduling:
      pool:
        size: 4

2、結果

由圖可知,增加了執行緒池,這樣使得定時任務A和B在不同的執行緒進行執行,但是定時任務A的第二次執行,依舊是在25秒後執行,由此可知這種方式其實解決的是不同定時任務之間的程序堵塞。

三、@Scheduled + @Async

1、程式碼

和前面相比,僅僅增加了設定

// 啟用非同步,動態建立執行緒
@EnableAsync  
@EnableScheduling
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
@Component
public class Task { 
    Logger logger = LoggerFactory.getLogger(Task.class);
    // 非同步,動態建立執行緒
    @Async
    @Scheduled(cron = "0/5 * * * * ?")
    public void taskTestA() throws InterruptedException {
        logger.info("A:");
        TimeUnit.SECONDS.sleep(20);
    }
    // 非同步,動態建立執行緒
    @Async
    @Scheduled(cron = "0/10 * * * * ?")
    public void taskTestB() {
        logger.info("B:");
    }
}

2、結果

由圖可知,啟用了非同步,使用了spring 預設的執行緒池,動態建立執行緒,這樣使得定時任務A和B在不同的執行緒進行執行,同時任務A的多次執行也是非同步執行,這樣就能確保所有定時任務不會延遲執行!

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com