最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

  • 我們需要改變定時任務的時間,此時我們就需要重啟項目
  • 我們不需要這個定時任務了,我們就要修改代碼,然后重啟項目
  • 后期我們又要開啟這個定時任務,我們又要修改代碼,然后重啟項目

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

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

實現(xiàn)

創(chuàng)建一個普通的SpringBoot項目,首先我們需要一個配置類,來配置定時任務的線程池

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)建一個接口,以供其它服務調(diào)用

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

接下來就是定時任務的編排核心處理類

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;
/**
 * 定時任務管理器
 */
@Component
public class ScheduleManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleManager.class);
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    /**
     * 內(nèi)部正在執(zhí)行的定時任務緩存
     */
    private Map<String,ScheduleTaskHolder> cache = new ConcurrentHashMap<>();
    /**
     * 啟動一個定時任務
     * scheduleTask:定時任務實現(xiàn)類
     * cron:cron表達式
     */
    public String startTask(ScheduleTask scheduleTask,String cron) {
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(scheduleTask, new CronTrigger(cron));
        //使用UUID生成定時任務的唯一key
        String key = UUID.randomUUID().toString();
        //將定時任務與定時任務結果封裝成ScheduleTaskHolder對象,
        //這個對象下文有源碼,也是我們自定義的
        ScheduleTaskHolder scheduleTaskHolder = new ScheduleTaskHolder(scheduleTask,scheduledFuture);
        //將正在執(zhí)行的定時任務緩存起來
        cache.put(key,scheduleTaskHolder);
        LOGGER.info("定時任務啟動成功,key = {}",key);
        return key;
    }
    /**
     * 停止一個定時任務
     * @param key:緩存里面的定時任務的key
     */
    public void stopTask(String key) {
        //基本判斷
        if(StrUtil.isBlank(key) || !cache.containsKey(key)) {
            return;
        }
        //從緩存中拿到這個定時任務
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            return;
        }
        ScheduledFuture scheduledFuture = scheduleTaskHolder.getScheduledFuture();
        //停止這個定時任務
        boolean isCancel = scheduledFuture.cancel(true);
        if(isCancel) {
            //停止成功,就從緩存中移除這個定時任務
            cache.remove(key);
            LOGGER.info("定時任務停止成功,key = {}",key);
        }else {
            LOGGER.error("定時任務停止失敗,key = {}",key);
        }
    }
    /**
     * 停止一個定時任務
     * @param key:緩存里面的定時任務的key
     * @param cron:新的cron表達式
     */
    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);
        }
        //先停止這個定時任務
        stopTask(key);
        //然后重啟開啟一個定時任務
        return startTask(scheduleTaskHolder.getScheduleTask(),cron);
    }
}

定時任務與定時任務結果的緩存封裝類

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;
/**
 * 定時任務管理器
 */
@Component
public class ScheduleManager {
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleManager.class);
    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    /**
     * 內(nèi)部正在執(zhí)行的定時任務緩存
     */
    private Map<String,ScheduleTaskHolder> cache = new ConcurrentHashMap<>();
    /**
     * 啟動一個定時任務
     * scheduleTask:定時任務實現(xiàn)類
     * cron:cron表達式
     */
    public String startTask(ScheduleTask scheduleTask,String cron) {
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(scheduleTask, new CronTrigger(cron));
        //使用UUID生成定時任務的唯一key
        String key = UUID.randomUUID().toString();
        //將定時任務與定時任務結果封裝成ScheduleTaskHolder對象,
        //這個對象下文有源碼,也是我們自定義的
        ScheduleTaskHolder scheduleTaskHolder = new ScheduleTaskHolder(scheduleTask,scheduledFuture);
        //將正在執(zhí)行的定時任務緩存起來
        cache.put(key,scheduleTaskHolder);
        LOGGER.info("定時任務啟動成功,key = {}",key);
        return key;
    }
    /**
     * 停止一個定時任務
     * @param key:緩存里面的定時任務的key
     */
    public void stopTask(String key) {
        //基本判斷
        if(StrUtil.isBlank(key) || !cache.containsKey(key)) {
            return;
        }
        //從緩存中拿到這個定時任務
        ScheduleTaskHolder scheduleTaskHolder = cache.get(key);
        if(scheduleTaskHolder == null) {
            return;
        }
        ScheduledFuture scheduledFuture = scheduleTaskHolder.getScheduledFuture();
        //停止這個定時任務
        boolean isCancel = scheduledFuture.cancel(true);
        if(isCancel) {
            //停止成功,就從緩存中移除這個定時任務
            cache.remove(key);
            LOGGER.info("定時任務停止成功,key = {}",key);
        }else {
            LOGGER.error("定時任務停止失敗,key = {}",key);
        }
    }
    /**
     * 停止一個定時任務
     * @param key:緩存里面的定時任務的key
     * @param cron:新的cron表達式
     */
    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);
        }
        //先停止這個定時任務
        stopTask(key);
        //然后重啟開啟一個定時任務
        return startTask(scheduleTaskHolder.getScheduleTask(),cron);
    }
}

測試

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

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

為了簡單,我直接在啟動類中編寫接口了,大家別跟我一樣這么懶哈

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;
    //啟動我們的定時任務
    @GetMapping("/startTask")
    public String startTask() {
        String key = scheduleManager.startTask(myTask, "0/10 * * * * ? ");
        return key;
    }
    //修改我們的定時任務
    @GetMapping("/changeTask")
    public String changeTask(@RequestParam("key") String key) {
        String keyValue = scheduleManager.changeTask(key, "0/20 * * * * ? ");
        return keyValue;
    }
    //停止我們的定時任務
    @GetMapping("/stopTask")
    public String stopTask(@RequestParam("key") String key) {
        scheduleManager.stopTask(key);
        return "ok";
    }
}

可以先啟動,然后修改,最后停止

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

相關文章

  • springboot項目之相互依賴報錯問題(基于idea)

    springboot項目之相互依賴報錯問題(基于idea)

    這篇文章主要介紹了springboot項目之相互依賴報錯問題(基于idea),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 如何設置springboot啟動端口

    如何設置springboot啟動端口

    spring boot是個好東西,可以不用容器直接在main方法中啟動,而且無需配置文件,方便快速搭建環(huán)境。下面給大家介紹springboot啟動端口的設置方法和spring boot創(chuàng)建應用端口沖突8080 問題,感興趣的朋友一起看看吧
    2017-08-08
  • 淺析java中String類型中“==”與“equal”的區(qū)別

    淺析java中String類型中“==”與“equal”的區(qū)別

    這篇文章主要介紹了淺析java中String類型中“==”與“equal”的區(qū)別,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • SpringBoot整合Redisson實現(xiàn)分布式鎖

    SpringBoot整合Redisson實現(xiàn)分布式鎖

    本文主要介紹了SpringBoot整合Redisson實現(xiàn)分布式鎖,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • springboot X-Accel-Redirect 大文件下載實現(xiàn)

    springboot X-Accel-Redirect 大文件下載實現(xiàn)

    本文主要介紹了springboot X-Accel-Redirect 大文件下載實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • Eclipse設置svn忽略文件或文件夾(svn:ignore)的操作

    Eclipse設置svn忽略文件或文件夾(svn:ignore)的操作

    這篇文章主要介紹了Eclipse設置svn忽略文件或文件夾(svn:ignore)的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 使用restTemplate遠程調(diào)controller路徑取數(shù)據(jù)

    使用restTemplate遠程調(diào)controller路徑取數(shù)據(jù)

    這篇文章主要介紹了使用restTemplate遠程調(diào)controller路徑取數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot Controller返回圖片的三種方式

    SpringBoot Controller返回圖片的三種方式

    在互聯(lián)網(wǎng)的世界里,圖片無處不在,它們是信息傳遞的重要媒介,也是視覺盛宴的一部分,而在Spring Boot項目中,如何優(yōu)雅地處理和返回圖片數(shù)據(jù),則成為了開發(fā)者們不得不面對的問題,今天,就讓我們一起來探索Spring Boot Controller的神奇轉換,需要的朋友可以參考下
    2024-07-07
  • Java連接MySQL數(shù)據(jù)庫并實現(xiàn)數(shù)據(jù)交互的示例

    Java連接MySQL數(shù)據(jù)庫并實現(xiàn)數(shù)據(jù)交互的示例

    數(shù)據(jù)庫是非常重要的一種存儲格式,可以大大提高存儲效率,本文主要介紹了Java連接MySQL數(shù)據(jù)庫并實現(xiàn)數(shù)據(jù)交互的示例,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • SpringBoot中項目結構的項目實踐

    SpringBoot中項目結構的項目實踐

    SpringBoot項目結構遵循Maven或Gradle的標準目錄結構,融入了SpringBoot的特定約定,本文就來介紹一下SpringBoot中項目結構的項目,感興趣的可以了解一下
    2025-03-03

最新評論

石柱| 红原县| 关岭| 岳西县| 天水市| 乐至县| 瓦房店市| 亚东县| 大兴区| 察隅县| 诏安县| 岳阳市| 个旧市| 辽阳市| 锡林浩特市| 忻州市| 芮城县| 沙雅县| 界首市| 绥棱县| 金堂县| 黎川县| 漳浦县| 屯门区| 元谋县| 法库县| 腾冲县| 边坝县| 湖口县| 康保县| 泰来县| 炎陵县| 广西| 车致| 德保县| 云梦县| 安西县| 桐柏县| 合阳县| 临湘市| 子洲县|