欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實(shí)現(xiàn)固定和動(dòng)態(tài)定時(shí)任務(wù)的三種方法

 更新時(shí)間:2023年09月14日 15:43:38   作者:搬山道猿  
定時(shí)器是我們項(xiàng)目中經(jīng)常會(huì)用到的,本文主要介紹了SpringBoot實(shí)現(xiàn)固定和動(dòng)態(tài)定時(shí)任務(wù)的三種方法,具有一定的參考價(jià)值,感興趣的可以了解一下

前言:

閱讀完本文:

  • 知曉 SpringBoot 用注解如何實(shí)現(xiàn)定時(shí)任務(wù)
  • 明白 SpringBoot 如何實(shí)現(xiàn)一個(gè)動(dòng)態(tài)定時(shí)任務(wù) (與數(shù)據(jù)庫相關(guān)聯(lián)實(shí)現(xiàn))
  • 理解 SpringBoot 實(shí)現(xiàn)設(shè)置時(shí)間執(zhí)行定時(shí)任務(wù) (使用 ThreadPoolTaskScheduler 實(shí)現(xiàn))

一、注解實(shí)現(xiàn)定時(shí)任務(wù)

用注解實(shí)現(xiàn)是真的簡(jiǎn)單,只要會(huì) cron 表達(dá)式就行。

第一步: 主啟動(dòng)類上加上 @EnableScheduling 注解

@EnableScheduling
@SpringBootApplication
public class SpringBootScheduled {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootScheduled.class);
    }
}

第二步:寫一個(gè)類,注入到Spring,關(guān)鍵就是 @Scheduled 注解。 () 里就是 cron 表達(dá)式,用來說明這個(gè)方法的執(zhí)行周期的。

/**
 * 定時(shí)任務(wù) 靜態(tài)定時(shí)任務(wù)
 *
 * 第一位,表示秒,取值0-59
 * 第二位,表示分,取值0-59
 * 第三位,表示小時(shí),取值0-23
 * 第四位,日期天/日,取值1-31
 * 第五位,日期月份,取值1-12
 * 第六位,星期,取值1-7,1表示星期天,2表示星期一
 * 第七位,年份,可以留空,取值1970-2099
 * @author crush
 * @since 1.0.0
 * @Date: 2021-07-27 21:13
 */
@Component
public class SchedulingTaskBasic {
    /**
     * 每五秒執(zhí)行一次
     */
    @Scheduled(cron = "*/5 * * * * ?")
    private void printNowDate() {
        long nowDateTime = System.currentTimeMillis();
        System.out.println("固定定時(shí)任務(wù)執(zhí)行:--->"+nowDateTime+",此任務(wù)為每五秒執(zhí)行一次");
    }
}

執(zhí)行效果:

二、動(dòng)態(tài)定時(shí)任務(wù)

其實(shí)也非常的簡(jiǎn)單。

2.1、建數(shù)據(jù)表

第一步:建個(gè)數(shù)據(jù)庫表。

CREATE TABLE `tb_cron`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '動(dòng)態(tài)定時(shí)任務(wù)時(shí)間表',
  `cron_expression` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '定時(shí)任務(wù)表達(dá)式',
  `cron_describe` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `tb_cron` VALUES (1, '0 0/1 * * * ?', '每分鐘執(zhí)行一次');

2.2、導(dǎo)入依賴,基礎(chǔ)編碼

第二步:導(dǎo)入數(shù)據(jù)庫相關(guān)依賴,做到能從數(shù)據(jù)庫查詢數(shù)據(jù)。大家都會(huì)。??‍♂?

第三步: 編碼

實(shí)體類:

@Data
@TableName("tb_cron")
public class Cron {
    private Long id;
    private String cronExpression;
    private String cronDescribe;
}

mapper層:

@Repository
public interface CronMapper extends BaseMapper<Cron> {
    @Select("select cron_expression from tb_cron where id=1")
    String getCron1();
}

2.3、主要實(shí)現(xiàn)代碼

第四步:寫一個(gè)類 實(shí)現(xiàn) SchedulingConfigurer ??

實(shí)現(xiàn) void configureTasks(ScheduledTaskRegistrar taskRegistrar); 方法,此方法的作用就是根據(jù)給定的 ScheduledTaskRegistrar 注冊(cè) TaskScheduler 和特定的Task實(shí)例

@Component
public class CompleteScheduleConfig implements SchedulingConfigurer {
    @Autowired
    @SuppressWarnings("all")
    CronMapper cronMapper;
    /**
     * 執(zhí)行定時(shí)任務(wù).
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1.添加任務(wù)內(nèi)容(Runnable)
                () -> System.out.println("執(zhí)行動(dòng)態(tài)定時(shí)任務(wù)1: " + LocalDateTime.now().toLocalTime()+",此任務(wù)執(zhí)行周期由數(shù)據(jù)庫中的cron表達(dá)式?jīng)Q定"),
                //2.設(shè)置執(zhí)行周期(Trigger)
                triggerContext -> {
                    //2.1 從數(shù)據(jù)庫獲取執(zhí)行周期
                    String cron = cronMapper.getCron1();
                    //2.2 合法性校驗(yàn).
                    if (cron!=null) {
                        // Omitted Code ..
                    }
                    //2.3 返回執(zhí)行周期(Date)
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );
    }
}

2.4、效果

注意:當(dāng)你修改了任務(wù)執(zhí)行周期后,生效時(shí)間為執(zhí)行完最近一次任務(wù)后。這一點(diǎn)是需要注意的,用生活中的例子理解就是我們?nèi)∠娫捒ǖ奶撞鸵惨聜€(gè)月生效,含義是一樣的。

三、實(shí)現(xiàn)設(shè)置時(shí)間定時(shí)任務(wù)

通常業(yè)務(wù)場(chǎng)景是我前言中說的那樣,是一次性的定時(shí)任務(wù)。如:我設(shè)置了我寫的這篇文章的發(fā)布時(shí)間為今天下午的兩點(diǎn),執(zhí)行完就刪除沒有了。一次性的。

實(shí)現(xiàn)主要依靠于 TaskScheduler ScheduledFuture<?> schedule(Runnable task, Trigger trigger); 方法來實(shí)現(xiàn)。其本質(zhì)和動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)是一樣的。

3.1、實(shí)現(xiàn)重點(diǎn)

代碼中都含有注解,不多做闡述。

import cn.hutool.core.convert.ConverterRegistry;
import com.crush.scheduled.entity.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
/**
 * @author crush
 */
@Component
@Slf4j
public class DynamicTaskService {
    /**
     * 以下兩個(gè)都是線程安全的集合類。
     */
    public Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();
    public List<String> taskList = new CopyOnWriteArrayList<String>();
    private final ThreadPoolTaskScheduler syncScheduler;
    public DynamicTaskService(ThreadPoolTaskScheduler syncScheduler) {
        this.syncScheduler = syncScheduler;
    }
    /**
     * 查看已開啟但還未執(zhí)行的動(dòng)態(tài)任務(wù)
     * @return
     */
    public List<String> getTaskList() {
        return taskList;
    }
    /**
     * 添加一個(gè)動(dòng)態(tài)任務(wù)
     *
     * @param task
     * @return
     */
    public boolean add(Task task) {
        // 此處的邏輯是 ,如果當(dāng)前已經(jīng)有這個(gè)名字的任務(wù)存在,先刪除之前的,再添加現(xiàn)在的。(即重復(fù)就覆蓋)
        if (null != taskMap.get(task.getName())) {
            stop(task.getName());
        }
        // hutool 工具包下的一個(gè)轉(zhuǎn)換類型工具類 好用的很
        ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
        Date startTime = converterRegistry.convert(Date.class, task.getStart());
        // schedule :調(diào)度給定的Runnable ,在指定的執(zhí)行時(shí)間調(diào)用它。
        //一旦調(diào)度程序關(guān)閉或返回的ScheduledFuture被取消,執(zhí)行將結(jié)束。
        //參數(shù):
        //任務(wù) – 觸發(fā)器觸發(fā)時(shí)執(zhí)行的 Runnable
        //startTime – 任務(wù)所需的執(zhí)行時(shí)間(如果這是過去,則任務(wù)將立即執(zhí)行,即盡快執(zhí)行)
        ScheduledFuture<?> schedule = syncScheduler.schedule(getRunnable(task), startTime);
        taskMap.put(task.getName(), schedule);
        taskList.add(task.getName());
        return true;
    }
    /**
     * 運(yùn)行任務(wù)
     *
     * @param task
     * @return
     */
    public Runnable getRunnable(Task task) {
        return () -> {
            log.info("---動(dòng)態(tài)定時(shí)任務(wù)運(yùn)行---");
            try {
                System.out.println("此時(shí)時(shí)間==>" + LocalDateTime.now());
                System.out.println("task中設(shè)定的時(shí)間==>" + task);
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("---end--------");
        };
    }
    /**
     * 停止任務(wù)
     *
     * @param name
     * @return
     */
    public boolean stop(String name) {
        if (null == taskMap.get(name)) {
            return false;
        }
        ScheduledFuture<?> scheduledFuture = taskMap.get(name);
        scheduledFuture.cancel(true);
        taskMap.remove(name);
        taskList.remove(name);
        return true;
    }
}

3.2、異步線程池的配置

/**
 * 異步線程池ThreadPoolExecutor 配置類
 *
 * @Author: crush
 * @Date: 2021-07-23 14:14
 */
@Configuration
public class ThreadPoolTaskExecutorConfig {
    @Bean
    public ThreadPoolTaskScheduler syncScheduler() {
        ThreadPoolTaskScheduler syncScheduler = new ThreadPoolTaskScheduler();
        syncScheduler.setPoolSize(5);
        // 這里給線程設(shè)置名字,主要是為了在項(xiàng)目能夠更快速的定位錯(cuò)誤。
        syncScheduler.setThreadGroupName("syncTg");
        syncScheduler.setThreadNamePrefix("syncThread-");
        syncScheduler.initialize();
        return syncScheduler;
    }
}

3.3、業(yè)務(wù)代碼

這里需要注意一個(gè)點(diǎn),我給項(xiàng)目中的 LocalDateTime 做了類型轉(zhuǎn)換。這里沒貼出來(主要是復(fù)制以前的代碼遺留下來的,源碼中都有)

大家簡(jiǎn)單使用,可以直接用注解 標(biāo)注在 LocalDateTime 屬性上即可。

package com.crush.scheduled.controller;
import com.crush.scheduled.entity.Task;
import com.crush.scheduled.service.DynamicTaskService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * @Author: crush
 * @Date: 2021-07-29 15:26
 * version 1.0
 */
@RestController
@RequestMapping("/dynamicTask")
public class DynamicTaskController {
    private final DynamicTaskService dynamicTask;
    public DynamicTaskController(DynamicTaskService dynamicTask) {
        this.dynamicTask = dynamicTask;
    }
    /**
     * 查看已開啟但還未執(zhí)行的動(dòng)態(tài)任務(wù)
     * @return
     */
    @GetMapping
    public List<String> getStartingDynamicTask(){
        return dynamicTask.getTaskList();
    }
    /**
     * 開啟一個(gè)動(dòng)態(tài)任務(wù)
     * @param task
     * @return
     */
    @PostMapping("/dynamic")
    public String startDynamicTask(@RequestBody Task task){
        // 將這個(gè)添加到動(dòng)態(tài)定時(shí)任務(wù)中去
        dynamicTask.add(task);
         return "動(dòng)態(tài)任務(wù):"+task.getName()+" 已開啟";
    }
    /**
     *  根據(jù)名稱 停止一個(gè)動(dòng)態(tài)任務(wù)
     * @param name
     * @return
     */
    @DeleteMapping("/{name}")
    public String stopDynamicTask(@PathVariable("name") String name){
        // 將這個(gè)添加到動(dòng)態(tài)定時(shí)任務(wù)中去
        if(!dynamicTask.stop(name)){
            return "停止失敗,任務(wù)已在進(jìn)行中.";
        }
        return "任務(wù)已停止";
    }
}

簡(jiǎn)單封裝的一個(gè)實(shí)體類:

/**
 * @Author: crush
 * @Date: 2021-07-29 15:35
 * version 1.0
 */
@Data
@Accessors(chain = true) // 方便鏈?zhǔn)骄帉?習(xí)慣所然 
public class Task {
    /**
     * 動(dòng)態(tài)任務(wù)名曾
     */
    private String name;
    /**
     * 設(shè)定動(dòng)態(tài)任務(wù)開始時(shí)間
     */
    private LocalDateTime start;
}

3.4、效果

開啟一個(gè)動(dòng)態(tài)任務(wù):

查看開啟還未執(zhí)行的動(dòng)態(tài)任務(wù):

執(zhí)行結(jié)果:

和我們代碼中是一模一樣的。

停止任務(wù):

再去查看就是已經(jīng)停止的拉

到此這篇關(guān)于SpringBoot實(shí)現(xiàn)固定和動(dòng)態(tài)定時(shí)任務(wù)的三種方法的文章就介紹到這了,更多相關(guān)SpringBoot 固定和動(dòng)態(tài)定時(shí)任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Netty分布式NioSocketChannel注冊(cè)到selector方法解析

    Netty分布式NioSocketChannel注冊(cè)到selector方法解析

    這篇文章主要為大家介紹了Netty分布式源碼分析NioSocketChannel注冊(cè)到selector方法的解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • spring?boot整合mongo查詢converter異常排查記錄

    spring?boot整合mongo查詢converter異常排查記錄

    這篇文章主要為大家介紹了spring?boot整合mongo查詢時(shí)拋出converter異常的排查解決記錄,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • Java 實(shí)現(xiàn)棧的三種方式

    Java 實(shí)現(xiàn)棧的三種方式

    這篇文章主要介紹了棧:LIFO(后進(jìn)先出),自己實(shí)現(xiàn)一個(gè)棧,要求這個(gè)棧具有push()、pop()(返回棧頂元素并出棧)、peek() (返回棧頂元素不出棧)、isEmpty()這些基本的方法,需要的朋友可以參考下
    2020-12-12
  • 打開.properties中文顯示unicode編碼問題以及解決

    打開.properties中文顯示unicode編碼問題以及解決

    這篇文章主要介紹了打開.properties中文顯示unicode編碼問題以及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • idea前后跳轉(zhuǎn)箭頭的快捷鍵

    idea前后跳轉(zhuǎn)箭頭的快捷鍵

    這篇文章主要介紹了idea前后跳轉(zhuǎn)箭頭的快捷鍵,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(44)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(44)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07
  • SpringBoot下的值注入(推薦)

    SpringBoot下的值注入(推薦)

    這篇文章主要介紹了SpringBoot下的值注入(推薦)的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Java?數(shù)據(jù)結(jié)構(gòu)進(jìn)階二叉樹題集下

    Java?數(shù)據(jù)結(jié)構(gòu)進(jìn)階二叉樹題集下

    二叉樹可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來說,最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將帶你通過實(shí)際題目來熟練掌握
    2022-04-04
  • Java簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸

    Java簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸

    下面小編就為大家?guī)硪黄狫ava簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • spring?boot對(duì)敏感信息進(jìn)行加解密的項(xiàng)目實(shí)現(xiàn)

    spring?boot對(duì)敏感信息進(jìn)行加解密的項(xiàng)目實(shí)現(xiàn)

    本文主要介紹了spring?boot對(duì)敏感信息進(jìn)行加解密的項(xiàng)目實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評(píng)論