SpringBoot進階之道-定時任務Scheduled


不少小夥伴在實際開發中,必定碰到過須要定時去執行某些業務邏輯的時候,解決方案有不少,好比MQ。不過在這裏博主介紹的是springboot提供的比較好用的定時任務組件Schedule。java

你們都知道spring建立定時任務so esay,下面有三種方式:spring

  • 基於註解 (@Scheduled)
  • 基於接口 (SchedulingConfigurer)
  • 基於註解設定多線程定時任務

1、基於註解 (@Scheduled)

須要注意的是@Scheduled默認是串行的,單線程,當開啓多個任務時,任務的執行時機會受上一個任務執行時間的影響。數據庫

@Configuration
@EnableScheduling    //開啓定時任務
public class ScheduleTask {
    //每10秒執行一次
    @Scheduled(cron = "0/10 * * * * ?")
    private void configureTasks() {
        System.out.println("我是一個定時任務");
    }
}
複製代碼

@Scheduled 除了cron還提供另外三種種方式: fixedRate,fixedDelay,initialDelay 一、cron表達式能夠定製化執行任務,可是執行的方式是與fixedDelay相近的,也是會按照上一次方法結束時間開始算起。 二、fixedDelay控制方法執行的間隔時間,是以上一次方法執行完開始算起,如上一次方法執行阻塞住了,那麼直到上一次執行完,並間隔給定的時間後,執行下一次。springboot

@Configuration
@EnableScheduling    //開啓定時任務
public class ScheduleTask {
    //每10秒執行一次
    @Scheduled(fixedDelay = 10000)
    private void configureTasks() {
        System.out.println("我是一個定時任務");
    }
}
複製代碼

三、fixedRate是按照必定的速率執行,是從上一次方法執行開始的時間算起,若是上一次方法阻塞住了,下一次也是不會執行,可是在阻塞這段時間內累計應該執行的次數,當再也不阻塞時,一會兒把這些所有執行掉,然後再按照固定速率繼續執行。bash

@Configuration
@EnableScheduling    //開啓定時任務
public class ScheduleTask {
    //每10秒執行一次
    @Scheduled(fixedRate = 10000)
    private void configureTasks() {
        System.out.println("我是一個定時任務");
    }
}
複製代碼

四、initialDelay = 10000 表示在容器啓動後,延遲10秒後再執行一次定時器。多線程

@Configuration
@EnableScheduling    //開啓定時任務
public class ScheduleTask {
    //容器啓動後,延遲10秒後再執行一次定時器,之後每10秒再執行一次該定時器。
    @Scheduled(initialDelay = 10000, fixedRate = 10000)
    private void configureTasks() {
        System.out.println("我是一個定時任務");
    }
}
複製代碼

2、基於接口 (SchedulingConfigurer)

有些小猿可能發現,使用@Scheduled 註解很方便,但缺點是當咱們調整了執行週期的時候,須要重啓應用才能生效,這多少有些不方便。爲了達到實時生效的效果,那麼可使用接口來完成定時任務。app

  • 下面案例從數據中獲取執行週期時間,而後動態執行定時任務:
@Configuration      
@EnableScheduling   //開啓定時任務
public class DynamicScheduleTask implements SchedulingConfigurer {

    //從數據獲取任務執行週期
    @Autowired
    private MyBatisMapper myBatisMapper;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1.添加任務內容(Runnable)
                () -> System.out.println("執行動態定時任務: " + LocalDateTime.now().toLocalTime()),
                //2.設置執行週期(Trigger)
                triggerContext -> {
                    //2.1從數據庫獲取執行週期
                    String cron = myBatisMapper.getCron();
                    //2.2 返回執行週期(Date)
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );
    }
}
複製代碼

數據庫表數據以下:ide

在數據庫表中插入時間週期.png

好,咱們啓動測試看看測試

執行動態定時任務: 17:17:00.008999
執行動態定時任務: 17:17:20.002501
執行動態定時任務: 17:17:30.001786
執行動態定時任務: 17:17:40.005512
執行動態定時任務: 17:17:50.005870
執行動態定時任務: 17:18:00.002189
執行動態定時任務: 17:18:10.001910
複製代碼

咱們能夠看到每10秒執行一次任務。那麼如今要求每5秒執行一次,該怎麼作呢?這個時候咱們只須要修改下數據庫數據便可,無需重啓。 spa

修改數據爲5秒每次.png
OK,咱們再看看控制檯打印的是什麼?

執行動態定時任務: 17:18:30.000902
執行動態定時任務: 17:18:40.001392
執行動態定時任務: 17:18:45.005027
執行動態定時任務: 17:18:50.001367
執行動態定時任務: 17:18:55.001356
執行動態定時任務: 17:19:00.001582
執行動態定時任務: 17:19:05.005676
執行動態定時任務: 17:19:10.001258
執行動態定時任務: 17:19:15.005272
複製代碼

成功每5秒執行一次。是否是很嗨~

3、基於註解設定多線程定時任務

前面講到了@Scheduled執行週期任務會受到上次一個任務的執行時間影響。那麼能夠開啓多線程執行週期任務。

@EnableScheduling   // 1.開啓定時任務
@EnableAsync        // 2.開啓多線程
@Component
public class MultiThreadScheduleTask {

    @Async
    @Scheduled(fixedDelay = 1000)  //間隔1秒
    public void first() throws InterruptedException {
        System.out.println("第一個定時任務開始 : " + LocalDateTime.now().toLocalTime() + "\r\n線程 : " + Thread.currentThread().getName());
        Thread.sleep(1000 * 10);
    }

    @Async
    @Scheduled(fixedDelay = 2000)
    public void second() {
        System.out.println("第二個定時任務開始 : " + LocalDateTime.now().toLocalTime() + "\r\n線程 : " + Thread.currentThread().getName());
    }
}
複製代碼

咱們重啓下項目看看控制檯輸出什麼:

第二個定時任務開始 : 17:27:01.024288
線程 : task-4
第一個定時任務開始 : 17:27:01.024393
線程 : task-7
第一個定時任務開始 : 17:27:02.027932
線程 : task-4
第二個定時任務開始 : 17:27:05.021294
線程 : task-1
第一個定時任務開始 : 17:27:05.021533
線程 : task-1
第一個定時任務開始 : 17:27:06.014213
複製代碼

看,因爲開啓了多線程,第一個任務的執行時間也不受其自己執行時間的限制。兩個任務也互不影響。

相關文章
相關標籤/搜索