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

基于Spring實(shí)現(xiàn)零重啟自由編排任務(wù)的定時(shí)管理器

 更新時(shí)間:2023年07月25日 14:03:46   作者:我是小趴菜  
我們發(fā)現(xiàn),我們使用Spring自帶的定時(shí)任務(wù)如果要有修改,那么就要修改代碼,然后重啟項(xiàng)目,所以本文就帶大家實(shí)現(xiàn)一個(gè)零重啟自由編排任務(wù)的定時(shí)管理器吧

大家好,我是小趴菜,關(guān)于定時(shí)任務(wù)相信大家在項(xiàng)目中使用了很多,我們一般都是使用Spring自帶的@EnableScheduling來(lái)實(shí)現(xiàn)定時(shí)任務(wù)

雖然Spring自帶的定時(shí)任務(wù)已經(jīng)可以滿足我們的業(yè)務(wù)需求,但是它還是有不足的地方

  • 我們需要改變定時(shí)任務(wù)的時(shí)間,此時(shí)我們就需要重啟項(xiàng)目
  • 我們不需要這個(gè)定時(shí)任務(wù)了,我們就要修改代碼,然后重啟項(xiàng)目
  • 后期我們又要開(kāi)啟這個(gè)定時(shí)任務(wù),我們又要修改代碼,然后重啟項(xiàng)目

我們發(fā)現(xiàn),我們使用Spring自帶的定時(shí)任務(wù)如果要有修改,那么就要修改代碼,然后重啟項(xiàng)目,那么有沒(méi)有辦法能夠讓我們不重啟項(xiàng)目就可以直接編排我們自己的定時(shí)任務(wù)呢?

答案是:有的,接下來(lái)我就帶大家實(shí)現(xiàn)一個(gè)零重啟自由編排任務(wù)的定時(shí)管理器

實(shí)現(xiàn)

創(chuàng)建一個(gè)普通的SpringBoot項(xiàng)目,首先我們需要一個(gè)配置類,來(lái)配置定時(shí)任務(wù)的線程池

package com.coco.schedule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class ScheduleConfig {
    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        //定制化我們的線程池
        taskScheduler.setPoolSize(1);        
        taskScheduler.setThreadNamePrefix("myTask-");
        return taskScheduler;
    }
}

創(chuàng)建一個(gè)接口,以供其它服務(wù)調(diào)用

/**
 * 定時(shí)任務(wù)的任務(wù)接口,需要實(shí)現(xiàn)Runnable接口
 */
public interface ScheduleTask extends Runnable {
    /**
     * 獲取定時(shí)任務(wù)的名稱
     */
    String getTaskName();
}

接下來(lái)就是定時(shí)任務(wù)的編排核心處理類

package com.coco.schedule;
import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
/**
 * 定時(shí)任務(wù)管理器
 */
@Component
public class ScheduleManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleManager.class);
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    /**
     * 內(nèi)部正在執(zhí)行的定時(shí)任務(wù)緩存
     */
    private Map<String,ScheduleTaskHolder> cache = new ConcurrentHashMap<>();
    /**
     * 啟動(dòng)一個(gè)定時(shí)任務(wù)
     * scheduleTask:定時(shí)任務(wù)實(shí)現(xiàn)類
     * cron:cron表達(dá)式
     */
    public String startTask(ScheduleTask scheduleTask,String cron) {
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(scheduleTask, new CronTrigger(cron));
        //使用UUID生成定時(shí)任務(wù)的唯一key
        String key = UUID.randomUUID().toString();
        //將定時(shí)任務(wù)與定時(shí)任務(wù)結(jié)果封裝成ScheduleTaskHolder對(duì)象,
        //這個(gè)對(duì)象下文有源碼,也是我們自定義的
        ScheduleTaskHolder scheduleTaskHolder = new ScheduleTaskHolder(scheduleTask,scheduledFuture);
        //將正在執(zhí)行的定時(shí)任務(wù)緩存起來(lái)
        cache.put(key,scheduleTaskHolder);
        LOGGER.info("定時(shí)任務(wù)啟動(dòng)成功,key = {}",key);
        return key;
    }
    /**
     * 停止一個(gè)定時(shí)任務(wù)
     * @param key:緩存里面的定時(shí)任務(wù)的key
     */
    public void stopTask(String key) {
        //基本判斷
        if(StrUtil.isBlank(key) || !cache.containsKey(key)) {
            return;
        }
        //從緩存中拿到這個(gè)定時(shí)任務(wù)
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            return;
        }
        ScheduledFuture scheduledFuture = scheduleTaskHolder.getScheduledFuture();
        //停止這個(gè)定時(shí)任務(wù)
        boolean isCancel = scheduledFuture.cancel(true);
        if(isCancel) {
            //停止成功,就從緩存中移除這個(gè)定時(shí)任務(wù)
            cache.remove(key);
            LOGGER.info("定時(shí)任務(wù)停止成功,key = {}",key);
        }else {
            LOGGER.error("定時(shí)任務(wù)停止失敗,key = {}",key);
        }
    }
    /**
     * 停止一個(gè)定時(shí)任務(wù)
     * @param key:緩存里面的定時(shí)任務(wù)的key
     * @param cron:新的cron表達(dá)式
     */
    public String changeTask(String key,String cron) {
        //基本判空處理
        if(StrUtil.isBlank(key) || StrUtil.isBlank(cron)) {
            throw new RuntimeException("key and cron mast not null");
        }
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            throw new RuntimeException("ScheduleTaskHolder not exist,key = {}" + key);
        }
        //先停止這個(gè)定時(shí)任務(wù)
        stopTask(key);
        //然后重啟開(kāi)啟一個(gè)定時(shí)任務(wù)
        return startTask(scheduleTaskHolder.getScheduleTask(),cron);
    }
}

定時(shí)任務(wù)與定時(shí)任務(wù)結(jié)果的緩存封裝類

package com.coco.schedule;
import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
/**
 * 定時(shí)任務(wù)管理器
 */
@Component
public class ScheduleManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleManager.class);
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    /**
     * 內(nèi)部正在執(zhí)行的定時(shí)任務(wù)緩存
     */
    private Map<String,ScheduleTaskHolder> cache = new ConcurrentHashMap<>();
    /**
     * 啟動(dòng)一個(gè)定時(shí)任務(wù)
     * scheduleTask:定時(shí)任務(wù)實(shí)現(xiàn)類
     * cron:cron表達(dá)式
     */
    public String startTask(ScheduleTask scheduleTask,String cron) {
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(scheduleTask, new CronTrigger(cron));
        //使用UUID生成定時(shí)任務(wù)的唯一key
        String key = UUID.randomUUID().toString();
        //將定時(shí)任務(wù)與定時(shí)任務(wù)結(jié)果封裝成ScheduleTaskHolder對(duì)象,
        //這個(gè)對(duì)象下文有源碼,也是我們自定義的
        ScheduleTaskHolder scheduleTaskHolder = new ScheduleTaskHolder(scheduleTask,scheduledFuture);
        //將正在執(zhí)行的定時(shí)任務(wù)緩存起來(lái)
        cache.put(key,scheduleTaskHolder);
        LOGGER.info("定時(shí)任務(wù)啟動(dòng)成功,key = {}",key);
        return key;
    }
    /**
     * 停止一個(gè)定時(shí)任務(wù)
     * @param key:緩存里面的定時(shí)任務(wù)的key
     */
    public void stopTask(String key) {
        //基本判斷
        if(StrUtil.isBlank(key) || !cache.containsKey(key)) {
            return;
        }
        //從緩存中拿到這個(gè)定時(shí)任務(wù)
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            return;
        }
        ScheduledFuture scheduledFuture = scheduleTaskHolder.getScheduledFuture();
        //停止這個(gè)定時(shí)任務(wù)
        boolean isCancel = scheduledFuture.cancel(true);
        if(isCancel) {
            //停止成功,就從緩存中移除這個(gè)定時(shí)任務(wù)
            cache.remove(key);
            LOGGER.info("定時(shí)任務(wù)停止成功,key = {}",key);
        }else {
            LOGGER.error("定時(shí)任務(wù)停止失敗,key = {}",key);
        }
    }
    /**
     * 停止一個(gè)定時(shí)任務(wù)
     * @param key:緩存里面的定時(shí)任務(wù)的key
     * @param cron:新的cron表達(dá)式
     */
    public String changeTask(String key,String cron) {
        //基本判空處理
        if(StrUtil.isBlank(key) || StrUtil.isBlank(cron)) {
            throw new RuntimeException("key and cron mast not null");
        }
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            throw new RuntimeException("ScheduleTaskHolder not exist,key = {}" + key);
        }
        //先停止這個(gè)定時(shí)任務(wù)
        stopTask(key);
        //然后重啟開(kāi)啟一個(gè)定時(shí)任務(wù)
        return startTask(scheduleTaskHolder.getScheduleTask(),cron);
    }
}

測(cè)試

寫好的程序怎么能不測(cè)試,首先我們需要?jiǎng)?chuàng)建一個(gè)自己的定時(shí)任務(wù)執(zhí)行的業(yè)務(wù)處理類,我這里創(chuàng)建了個(gè)MyTask.class

package com.coco.schedule;
import org.springframework.stereotype.Component;
//需要實(shí)現(xiàn)ScheduleTask接口
@Component
public class MyTask implements ScheduleTask {
    @Override
    public String getTaskName() {
        return "MyTask";
    }
    @Override
    public void run() {
        //在這里就是我們定時(shí)任務(wù)的業(yè)務(wù)邏輯
        System.out.println("這是自定義的定時(shí)起任務(wù)");
    }
}

為了簡(jiǎn)單,我直接在啟動(dòng)類中編寫接口了,大家別跟我一樣這么懶哈

package com.coco;
import com.coco.schedule.MyTask;
import com.coco.schedule.ScheduleManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class,args);
    }
    @Resource
    private ScheduleManager scheduleManager;
    @Resource
    private MyTask myTask;
    //啟動(dòng)我們的定時(shí)任務(wù)
    @GetMapping("/startTask")
    public String startTask() {
        String key = scheduleManager.startTask(myTask, "0/10 * * * * ? ");
        return key;
    }
    //修改我們的定時(shí)任務(wù)
    @GetMapping("/changeTask")
    public String changeTask(@RequestParam("key") String key) {
        String keyValue = scheduleManager.changeTask(key, "0/20 * * * * ? ");
        return keyValue;
    }
    //停止我們的定時(shí)任務(wù)
    @GetMapping("/stopTask")
    public String stopTask(@RequestParam("key") String key) {
        scheduleManager.stopTask(key);
        return "ok";
    }
}

可以先啟動(dòng),然后修改,最后停止

到此這篇關(guān)于基于Spring實(shí)現(xiàn)零重啟自由編排任務(wù)的定時(shí)管理器的文章就介紹到這了,更多相關(guān)Spring定時(shí)管理器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目)

    IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目)

    這篇文章主要介紹了IDEA創(chuàng)建parent項(xiàng)目(聚合項(xiàng)目),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 全面了解Java反射機(jī)制

    全面了解Java反射機(jī)制

    Java的反射機(jī)制在實(shí)踐中可謂無(wú)處不在,如果你已經(jīng)工作幾年,還對(duì)Java的反射機(jī)制一知半解,那么這篇文章絕對(duì)值得你讀一讀。
    2020-03-03
  • Java值得使用Lambda的8個(gè)場(chǎng)景合集

    Java值得使用Lambda的8個(gè)場(chǎng)景合集

    可能對(duì)不少人來(lái)說(shuō),Lambda顯得陌生又復(fù)雜,覺(jué)得Lambda會(huì)導(dǎo)致代碼可讀性下降,但畢竟2023年了,JDK都出了那么多新版本,是時(shí)候試試Lambda了
    2023-08-08
  • Springboot多環(huán)境開(kāi)發(fā)及使用方法

    Springboot多環(huán)境開(kāi)發(fā)及使用方法

    這篇文章主要介紹了Springboot多環(huán)境開(kāi)發(fā)及多環(huán)境設(shè)置使用、多環(huán)境分組管理的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    這篇文章主要介紹了Springboot整合JPA配置多數(shù)據(jù)源,JPA可以通過(guò)實(shí)體類生成數(shù)據(jù)庫(kù)的表,同時(shí)自帶很多增刪改查方法,大部分sql語(yǔ)句不需要我們自己寫,配置完成后直接調(diào)用方法即可,很方便
    2022-11-11
  • java8?Stream大數(shù)據(jù)量List分批處理切割方式

    java8?Stream大數(shù)據(jù)量List分批處理切割方式

    這篇文章主要介紹了java8?Stream大數(shù)據(jù)量List分批處理切割方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • java生成sm2/hutool生成公鑰私鑰代碼示例

    java生成sm2/hutool生成公鑰私鑰代碼示例

    這篇文章主要給大家介紹了關(guān)于java生成sm2/hutool生成公鑰私鑰的相關(guān)資料,Java是一種廣泛使用的編程語(yǔ)言,可以用來(lái)生成公鑰和私鑰文件,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式

    Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式

    這篇文章主要介紹了Spring Boot中單例類實(shí)現(xiàn)對(duì)象的注入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java中synchronized的四種用法詳解

    Java中synchronized的四種用法詳解

    這篇文章主要介紹了Java中synchronized的四種用法詳解,當(dāng)我們處理多線程處理同步問(wèn)題的時(shí)候就會(huì)用到synchronized這個(gè)關(guān)鍵字,下面介紹下synchronized的四種用法,需要的朋友可以參考下
    2024-01-01
  • 基于SpringBoot和Vue3的博客平臺(tái)文章詳情與評(píng)論功能實(shí)現(xiàn)

    基于SpringBoot和Vue3的博客平臺(tái)文章詳情與評(píng)論功能實(shí)現(xiàn)

    在前面的教程中,我們已經(jīng)實(shí)現(xiàn)了基于Spring Boot和Vue3的發(fā)布、編輯、刪除文章功能以及文章列表與分頁(yè)功能。本教程將引導(dǎo)您實(shí)現(xiàn)博客平臺(tái)的文章詳情與評(píng)論功能,需要的朋友可以參考一下
    2023-04-04

最新評(píng)論