天天看點

Java 定時任務技術發展曆程

Java 定時任務技術發展曆程

定時任務是每個業務常見的需求,比如每分鐘掃描逾時支付的訂單,每小時清理一次資料庫曆史資料,每天統計前一天的資料并生成報表等等。常見的解決方案有XXL-JOB、Spring-Task等。本篇文章着重于探讨Java 定時任務技術的發展曆程。

一、Timer

java.util.Timer 是JDK原生的工具類,用于建立定時任務。

建立 java.util.TimerTask 任務,在 run 方法中實作業務邏輯。通過 java.util.Timer 進行排程,支援按照固定頻率或指定Date時刻執行。所有的 TimerTask 是在同一個線程中串行執行,互相影響。也就是說,對于同一個 Timer 裡的多個 TimerTask 任務,如果一個 TimerTask 任務在執行中,其它 TimerTask 即使到達執行的時間,也隻能排隊等待。如果有異常産生,線程将退出,整個定時任務就失敗。

TimerTask timerTask1 = new TimerTask() {
   @SneakyThrows
   @Override
   public void run() {
      System.out.println("timerTask1 run ...");
      Thread.sleep(10000);
      System.out.println("timerTask1 finish ...");
   }
};
TimerTask timerTask2 = new TimerTask() {
   @Override
   public void run() {
      System.out.println(System.currentTimeMillis());
      System.out.println("timerTask2 run ...");
   }
};
Timer timer = new Timer();
DateTime date = DateUtil.parse("2022-08-04 15:30:00", DatePattern.NORM_DATETIME_PATTERN);
timer.schedule(timerTask1, date);
timer.schedule(timerTask2, 15000);
複制代碼      

二、ScheduledExecutorService

ScheduledExecutorService 是 java.util.concurrent包下基于線程池設計的定時任務解決方案。

每個排程任務都會配置設定到線程池中的一個線程去執行,解決 Timer 定時器無法并發執行的問題,支援 fixedRate 和 fixedDelay。

public class ScheduledExecutorServiceTest {
   private static final int CORE_SIZE = 5;

   public static void main(String[] args) {
      ScheduledExecutorService executorService = Executors.newScheduledThreadPool(CORE_SIZE);
      // 按照固定頻率執行,每隔5秒跑一次
      executorService.scheduleAtFixedRate(() -> System.out.println("hello fixedRate"), 10, 5, TimeUnit.SECONDS);
      // 按照固定延時執行,上次執行完後隔5秒執行下一次
      executorService.scheduleWithFixedDelay(() -> System.out.println("hello fixedDelay"), 10, 5, TimeUnit.SECONDS);
   }
}
複制代碼      

三、Spring Task

Spring Task是 SpringBoot提供的輕量級定時任務工具。

我們通過注解可以很友善的配置,支援 cron 表達式、fixedRate、fixedDelay。

@Component
@EnableScheduling
public class SpringTaskTest {

   /**
    * 每分鐘的第30秒跑一次
    */
   @Scheduled(cron = "30 * * * * ?")
   public void task1() throws InterruptedException {
      System.out.println("hello cron");
   }

   /**
    * 每隔5秒跑一次
    */
   @Scheduled(fixedRate = 5000)
   public void task2() throws InterruptedException {
      System.out.println("hello fixedRate");
   }
   
   /**
    * 上次跑完隔3秒再跑
    */
   @Scheduled(fixedDelay = 3000)
   public void task3() throws InterruptedException {
      System.out.println("hello fixedDelay");
   }
}
複制代碼      

四、Quartz

五、XXL-JOB