springBoot中使用定時任務


簡單示例

導入依賴

springBoot已經默認集成了定時任務的依賴,只需要引入基本的依賴就可以使用定時任務。

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

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

    </dependencies>

啟動類配置

在啟動類中需要加入@EnableScheduling注解,意思是開啟定時任務。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * Author: YaoQi
 * Date: 2018/9/28 21:37
 * Description: springBoot schedule
 */
@SpringBootApplication
@EnableScheduling
public class ScheduleApp {

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

定時任務Demo

寫一個定時任務demo,每秒種打印一次日志,並打印當前時間驗證當前任務執行周期。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

/**
 * Author: YaoQi
 * Date: 2018/9/28 21:40
 * Description: Scheduled Task
 */
@Service
public class ScheduleTask {

    private static final Logger logger = LoggerFactory.getLogger(ScheduleTask.class);

    @Scheduled(cron = "*/1 * * * * ?")
    public void execute() {
        logger.info("print word.");
        logger.info(String.valueOf(System.currentTimeMillis()));
    }
}

運行結果:

運行結果

示例分析

從上圖的結果中看:該任務基本是每秒種執行一次,如果不手動停止,程序會一直執行下去,並且從日志中看,這個任務的執行周期是1s左右,剛好和設置的cron表達式一致;並且執行這個任務的線程一直是poll-1-thread-1這個線程。這就意味着,這個定時任務啟動是由單獨的一個線程去執行的。

這時候,可能會有幾個問題:

如果任務執行的時間比執行周期要短,這個任務會怎么執行?

如果有多個任務執行,還會是一個線程去執行這個任務嗎?

首先驗證第一個問題,當任務執行的時間比執行周期短時,任務的執行情況。

@Scheduled(cron = "*/1 * * * * ?")
    public void execute() {
        logger.info("print word.");
        logger.info(String.valueOf(System.currentTimeMillis()));
        try {
            Thread.sleep(6000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

執行結果:每次任務的執行時間間隔為7秒,並且是同一個線程在執行。

執行結果

如果有多個任務執行,任務的執行情況。

@Scheduled(cron = "*/1 * * * * ?")
    public void execute() {
        logger.info("print word.");
        try {
            Thread.sleep(6000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(cron = "*/1 * * * * ?")
    public void execute1() {
        logger.info(String.valueOf(System.currentTimeMillis()));
        logger.info("write message.");
    }

執行結果:

執行結果

執行結果:第二個每秒執行一次的任務的並沒有安裝設定的執行周期執行,運行結果並沒有達到預期。並且兩個任務都是由同一個線程去運行。

多任務模式

示例分析中問題2的原因就是執行多個任務並不是多個線程執行,導致執行第一個任務時,第二個任務進入等待狀態。springBoot中提供了多線程運行定時任務的方式。

@Configuration
public class ScheduleConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(3));
    }
}

增加一個配置類,設置線程池,並設置線程池大小,這里的線程池大小就仁者見仁了,和你程序中的任務的個數有關系,也和機器的核數有關系。

通過配置線程池就能讓每個任務獨立執行,不受其他任務的影響,因為是在不同的線程中執行的,但如果涉及到公共資源就另當別論了。

執行結果:

在不同的線程中執行

配置執行周期

上述中的執行周期都是以cron表達式定義的,這種方式最靈活,但是上文中的表達式都寫到代碼中去了,不便於修改,這里提供一種配置方式,直接用表達式獲取yml中的配置信息。

scheduleTask:
  cron1: "*/1 * * * * ?"
  cron2: "*/1 * * * * ?"

在yml中添加cron的配置信息。然后在Java注解中可以直接獲取。

@Scheduled(cron = "${scheduleTask.cron2}")
    public void execute1() {
        logger.info(String.valueOf(System.currentTimeMillis()));
        logger.info("write message.");
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM