Spring Boot (29) 定時任務

使用場景:數據定時增量同步,定時發送郵件,爬蟲定時抓取java

 

定時任務概述web

  定時任務:顧名思義就是在特定/指spring

定的時間進行工做,好比咱們的手機鬧鐘,他就是一種定時的任務。多線程

實現方式:併發

  1.Timer:JDK自帶的java.util.Timer;經過調度java.util.TimerTask的方式 讓程序按照某一個頻率執行,但不能在指定時間運行,通常使用較少。app

  2.ScheduledExecutorService:JDK1.5增長的,位於Java.util.concurrent包種,是基於線程池設計的定時任務類,每一個調度任務都會被分配到線程池中,併發執行,互不影響。異步

  3.Spring Task:spring 3.0之後新增了task,一個輕量級的Quartz,功可以用,用法簡單。jsp

  4.Quartz:功能最爲強大的調度器,可讓程序在指定時間執行,也能夠按照某一個頻率執行,他還能夠動態開關,可是配置起來比較複雜,現現在開源社區中已經不少基於Quartz 實現的分佈式定時任務項目。分佈式

 

Timer方式ide

  基於Timer實現的定時調度,目前應用較少,不推薦使用

    @GetMapping("/test")
    public String test() {

        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("執行任務"+ LocalDateTime.now());
            }
        };
        Timer timer = new Timer();
        //參數1 須要執行的任務 參數2 延遲時間毫秒 參數3 間隔時間毫秒
        timer.schedule(timerTask,5000,3000);

        return "test";
    }

 

ScheduledExecutorService

  基於ScheduledExecutorService實現的調度任務,它與TImer很相似,但它的效果更好,多線程並行處理定時任務時,Timer運行多個TimeTask時,只要其中有一個因任務報錯沒有捕獲拋出的異常,其餘任務便會自動終止運行,使用scheduledExecutorService能夠規避這個問題

    @GetMapping("/cheduled")
    public String cheduled() {

        ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
        //參數1具體執行的任務 2首次執行的延遲時間 3任務執行間隔 4間隔時間單位
        service.scheduleAtFixedRate(()->System.out.println("執行任務"+LocalDateTime.now()),0,3, TimeUnit.SECONDS);

        return "cheduled";
    }

 

Spring Task(關鍵)

導入依賴

在pom.xml中添加spring-boot-starter-web依賴便可,它包含了spring-context,定時任務相關的就屬於這個JAR下的org.springframework.scheduling包中

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

定時任務

@Scheduled 定時任務的核心

  cron:cron表達式,根據表達式循環執行,與fixedRate屬性不一樣的是它將時間進行了切割

  fixeRate:每隔多久執行一次,無視工做時間(@Scheduled(fixedRate = 1000))假設第一次工做時間爲2018-06-15 00:00:00,工做時長爲5秒,那麼下次任務的時間就是 2018-06-15 00:00:05)

  initialDelay:第一次執行延遲時間,只是作延遲的設定,與fixedDelay關係密切,配合使用。

@Async 表明任務能夠進行一步工做,由本來的串行改成並行

package com.spring.boot.utils;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class SpringTaskDemo {
    @Async
    @Scheduled(cron = "0/1 * * * * *")
    public void scheduled1() throws InterruptedException {
        Thread.sleep(3000);
        System.out.println("scheduled1 每1秒執行一次" + LocalDateTime.now());
    }

    @Scheduled(fixedRate = 1000)
    public void scheduled2() throws InterruptedException {
        Thread.sleep(3000);
        System.out.println("scheduled2 每1秒執行一次" + LocalDateTime.now());
    }


    @Scheduled(fixedRate = 3000)
    public void scheduled3() throws InterruptedException {
        Thread.sleep(5000);
        System.out.println("scheduled3 航次執行完畢後間隔3秒繼續執行" + LocalDateTime.now());
    }
}

cron表達式在線生成: http://www.pdtools.net/tools/becron.jsp

啓動類中@EnableScheduling註解 表示開啓對@Scheduled註解的解析;同時new ThreadPoolTaskScheduler()也是至關的關鍵,默認狀況下的private volatile int poolSize = 1;這就致使了多個任務的狀況下容易出現競爭狀況(多個任務的狀況下,若是第一個任務沒執行完畢,後續的任務將會進入等待狀態)。

@EnableAsync 表明開啓@Async異步的解析,並行化運行

@EnableAsync
@EnableScheduling
@SpringBootApplication
public class BootApplication{

    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class,args);
    }

    @Bean
    public TaskScheduler taskScheduler(){
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        return taskScheduler;
    }
}

測試

啓動項目 觀察日誌信息以下:

scheduled2 每1秒執行一次2018-06-14T17:33:42.245
scheduled1 每1秒執行一次2018-06-14T17:33:43.030
scheduled1 每1秒執行一次2018-06-14T17:33:44.009
scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:44.244
scheduled1 每1秒執行一次2018-06-14T17:33:45.011
scheduled2 每1秒執行一次2018-06-14T17:33:45.249
scheduled1 每1秒執行一次2018-06-14T17:33:46.008
scheduled1 每1秒執行一次2018-06-14T17:33:47.008
scheduled1 每1秒執行一次2018-06-14T17:33:48.010
scheduled2 每1秒執行一次2018-06-14T17:33:48.254
scheduled1 每1秒執行一次2018-06-14T17:33:49.005
scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:49.247
scheduled1 每1秒執行一次2018-06-14T17:33:50.008
scheduled1 每1秒執行一次2018-06-14T17:33:51.006
scheduled2 每1秒執行一次2018-06-14T17:33:51.258
scheduled1 每1秒執行一次2018-06-14T17:33:52.006
scheduled1 每1秒執行一次2018-06-14T17:33:53.008
scheduled1 每1秒執行一次2018-06-14T17:33:54.007
scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:54.252
scheduled2 每1秒執行一次2018-06-14T17:33:54.262
scheduled1 每1秒執行一次2018-06-14T17:33:55.007
scheduled1 每1秒執行一次2018-06-14T17:33:56.007
scheduled1 每1秒執行一次2018-06-14T17:33:57.005
scheduled2 每1秒執行一次2018-06-14T17:33:57.266
scheduled1 每1秒執行一次2018-06-14T17:33:58.007
scheduled1 每1秒執行一次2018-06-14T17:33:59.006
scheduled3 航次執行完畢後間隔3秒繼續執行2018-06-14T17:33:59.257
相關文章
相關標籤/搜索