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

SpringBoot實(shí)現(xiàn)動(dòng)態(tài)多線程并發(fā)定時(shí)任務(wù)

 更新時(shí)間:2022年05月16日 10:16:08   作者:typ1805  
這篇文章主要為大家詳細(xì)介紹了SpringBoot實(shí)現(xiàn)動(dòng)態(tài)多線程并發(fā)定時(shí)任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了SpringBoot實(shí)現(xiàn)動(dòng)態(tài)多線程并發(fā)定時(shí)任務(wù)的具體代碼,供大家參考,具體內(nèi)容如下

實(shí)現(xiàn)定時(shí)任務(wù)有多種方式,使用spring自帶的,繼承SchedulingConfigurer的方式。

一、實(shí)現(xiàn)

1、啟動(dòng)類

在啟動(dòng)類添加注解@EnableScheduling開啟,不然不起用做。

2、新建任務(wù)類

添加注解@Component注冊(cè)到spring的容器中。

package com.example.demo.task;

import com.example.demo.entity.MyTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledFuture;

/**
 * @path:com.example.demo.task.ScheduledTask.java
 * @className:ScheduledTask.java
 * @description:定時(shí)任務(wù)
 * @author:tanyp
 * @dateTime:2020/7/23 21:37 
 * @editNote:
 */
@Slf4j
@Component
public class ScheduledTask implements SchedulingConfigurer {

    private volatile ScheduledTaskRegistrar registrar;

    private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledFutures = new ConcurrentHashMap<>();

    private final ConcurrentHashMap<String, CronTask> cronTasks = new ConcurrentHashMap<>();

    /**
     * 默認(rèn)啟動(dòng)10個(gè)線程
     */
    private static final Integer DEFAULT_THREAD_POOL = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar registrar) {
        registrar.setScheduler(Executors.newScheduledThreadPool(DEFAULT_THREAD_POOL));
        this.registrar = registrar;
    }

    @PreDestroy
    public void destroy() {
        this.registrar.destroy();
    }

    /**
     * @methodName:refreshTask
     * @description:初始化任務(wù)
     * 1、從數(shù)據(jù)庫(kù)獲取執(zhí)行任務(wù)的集合【TxTask】
     * 2、通過調(diào)用 【refresh】 方法刷新任務(wù)列表
     * 3、每次數(shù)據(jù)庫(kù)中的任務(wù)發(fā)生變化后重新執(zhí)行【1、2】
     * @author:tanyp
     * @dateTime:2020/7/23 21:37
     * @Params: [tasks]
     * @Return: void
     * @editNote:
     */
    public void refreshTask(List<MyTask> tasks) {
        // 刪除已經(jīng)取消任務(wù)
        scheduledFutures.keySet().forEach(key -> {
            if (Objects.isNull(tasks) || tasks.size() == 0) {
                scheduledFutures.get(key).cancel(false);
                scheduledFutures.remove(key);
                cronTasks.remove(key);
                return;
            }
            tasks.forEach(task -> {
                if (!Objects.equals(key, task.getTaskId())) {
                    scheduledFutures.get(key).cancel(false);
                    scheduledFutures.remove(key);
                    cronTasks.remove(key);
                    return;
                }
            });
        });

        // 添加新任務(wù)、更改執(zhí)行規(guī)則任務(wù)
        tasks.forEach(txTask -> {
            String expression = txTask.getExpression();
            // 任務(wù)表達(dá)式為空則跳過
            if (StringUtils.isEmpty(expression)) {
                return;
            }

            // 任務(wù)已存在并且表達(dá)式未發(fā)生變化則跳過
            if (scheduledFutures.containsKey(txTask.getTaskId()) && cronTasks.get(txTask.getTaskId()).getExpression().equals(expression)) {
                return;
            }

            // 任務(wù)執(zhí)行時(shí)間發(fā)生了變化,則刪除該任務(wù)
            if (scheduledFutures.containsKey(txTask.getTaskId())) {
                scheduledFutures.get(txTask.getTaskId()).cancel(false);
                scheduledFutures.remove(txTask.getTaskId());
                cronTasks.remove(txTask.getTaskId());
            }
            CronTask task = new CronTask(new Runnable() {
                @Override
                public void run() {
                    // 執(zhí)行業(yè)務(wù)邏輯
                    try {
                        log.info("執(zhí)行單個(gè)任務(wù),任務(wù)ID【{}】執(zhí)行規(guī)則【{}】", txTask.getTaskId(), txTask.getExpression());
                        System.out.println("==========================執(zhí)行任務(wù)=============================");
                    } catch (Exception e) {
                        log.error("執(zhí)行發(fā)送消息任務(wù)異常,異常信息:{}", e);
                    }
                }
            }, expression);
            ScheduledFuture<?> future = registrar.getScheduler().schedule(task.getRunnable(), task.getTrigger());
            cronTasks.put(txTask.getTaskId(), task);
            scheduledFutures.put(txTask.getTaskId(), future);
        });
    }

}

3、創(chuàng)建自啟動(dòng)任務(wù)類

package com.example.demo.task;

import com.example.demo.task.ScheduledTask;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * @path:com.example.demo.task.MyApplicationRunner.java
 * @className:ScheduledTask.java
 * @description:自啟動(dòng)
 * @author:tanyp
 * @dateTime:2020/7/23 21:37 
 * @editNote:
 */
@Slf4j
@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Autowired
    private ScheduledTask scheduledTask;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("================項(xiàng)目啟動(dòng)初始化定時(shí)任務(wù)====開始===========");
        /**
         * 初始化三個(gè)任務(wù):
         * 1、10秒執(zhí)行一次
         * 2、15秒執(zhí)行一次
         * 3、20秒執(zhí)行一次
         */
        List<MyTask> tasks = Arrays.asList(
                MyTask.builder().taskId("10001").expression("*/10 * * * * ?").build(),
                MyTask.builder().taskId("10002").expression("*/15 * * * * ?").build(),
                MyTask.builder().taskId("10003").expression("*/20 * * * * ?").build()
        );
        scheduledTask.refreshTask(tasks);
        log.info("================項(xiàng)目啟動(dòng)初始化定時(shí)任務(wù)====完成==========");
    }
}

4、實(shí)體

package com.example.demo.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @path:com.example.demo.entity.MyTask.java
 * @className:MyTask.java
 * @description:任務(wù)實(shí)體
 * @author:tanyp
 * @dateTime:2020/7/23 21:41 
 * @editNote:
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyTask {

    /**
     * 任務(wù)id
     */
    private String taskId;

    /**
     * 任務(wù)執(zhí)行規(guī)則時(shí)間
     */
    private String expression;
}

二、測(cè)試

初始化三個(gè)任務(wù),分別為:

10秒執(zhí)行一次(*/10 * * * * ?)
15秒執(zhí)行一次(*/15 * * * * ?)
20秒執(zhí)行一次(*/20 * * * * ?)

測(cè)試效果:

可以看到初始化的三個(gè)任務(wù)都在執(zhí)行,并且是不用的線程在執(zhí)行。

三、動(dòng)態(tài)使用方式

1、啟動(dòng)方式有兩種:

  • 啟動(dòng)項(xiàng)目后,手動(dòng)調(diào)用ScheduledTask.refreshTask(List tasks),并初始化任務(wù)列表;
  • 使用我測(cè)試中的方式,配置項(xiàng)目啟動(dòng)完成后自動(dòng)調(diào)用初始任務(wù)的方法,并初始化任務(wù)列表。

2、數(shù)據(jù)初始化

只需要給 List集合賦值并調(diào)用refreshTask()方法即可:

  • 根據(jù)業(yè)務(wù)需求修改MyTask實(shí)體類;
  • 這里的初始化數(shù)據(jù)可以從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)賦值給集合;

例如:從mysql讀取任務(wù)配置表的數(shù)據(jù),調(diào)用refreshTask()方法。

3、如何動(dòng)態(tài)?

  • 修改:修改某一項(xiàng)正在執(zhí)行的任務(wù)規(guī)則;
  • 添加:添加一項(xiàng)新的任務(wù);
  • 刪除:停止某一項(xiàng)正在執(zhí)行的任務(wù)。

例如:我們有一張任務(wù)配置表,此時(shí)進(jìn)行分別新增一條或多條數(shù)據(jù)、刪除一條或多條數(shù)據(jù)、改一條數(shù)據(jù),只需要完成以上任何一項(xiàng)操作后,重新調(diào)用一下refreshTask()方法即可。

怎么重新調(diào)用 refreshTask()方法:可以另外啟一個(gè)任務(wù)實(shí)時(shí)監(jiān)控任務(wù)表的數(shù)據(jù)變化。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Mybatis日志模塊的適配器模式詳解

    Mybatis日志模塊的適配器模式詳解

    這篇文章主要介紹了Mybatis日志模塊的適配器模式詳解,,mybatis用了適配器模式來兼容這些框架,適配器模式就是通過組合的方式,將需要適配的類轉(zhuǎn)為使用者能夠使用的接口
    2022-08-08
  • SpringCloud開發(fā)課程查詢功能

    SpringCloud開發(fā)課程查詢功能

    這篇文章主要介紹了SpringCloud開發(fā)課程查詢功能,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • java中實(shí)現(xiàn)漢字按照拼音排序(示例代碼)

    java中實(shí)現(xiàn)漢字按照拼音排序(示例代碼)

    這篇文章主要是對(duì)java中將漢字按照拼音排序的實(shí)現(xiàn)代碼進(jìn)行了詳細(xì)的分析介紹。需要的朋友可以過來參考下,希望對(duì)大家有所幫助
    2013-12-12
  • JAVA實(shí)現(xiàn)掃描線算法(超詳細(xì))

    JAVA實(shí)現(xiàn)掃描線算法(超詳細(xì))

    掃描線算法就是從Ymin開始掃描,然后構(gòu)建出NET,之后根據(jù)NET建立AET。接下來本文通過代碼給大家介紹JAVA實(shí)現(xiàn)掃描線算法,感興趣的朋友一起看看吧
    2019-10-10
  • Idea如何配置Maven才能優(yōu)先從本地倉(cāng)庫(kù)獲取依賴(親測(cè)方法有效)

    Idea如何配置Maven才能優(yōu)先從本地倉(cāng)庫(kù)獲取依賴(親測(cè)方法有效)

    對(duì)于Idea怎么配置Maven才能優(yōu)先從本地倉(cāng)庫(kù)獲取依賴,網(wǎng)上說法有很多種,都不太靠譜,最終都沒有效果,最好的解決方法是通過修改maven配置文件settings.xml,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • java反射方式創(chuàng)建代碼詳解

    java反射方式創(chuàng)建代碼詳解

    在本篇文章里小編給大家整理的是一篇關(guān)于java反射方式創(chuàng)建代碼詳解內(nèi)容,對(duì)此有興趣的朋友們可以學(xué)習(xí)下。
    2021-01-01
  • SpringBoot配置 Druid 三種方式(包括純配置文件配置)

    SpringBoot配置 Druid 三種方式(包括純配置文件配置)

    本文給大家分享在項(xiàng)目中用純 YML(application.yml 或者 application.properties)文件、Java 代碼配置 Bean 和注解三種方式配置 Alibaba Druid 用于監(jiān)控或者查看 SQL 狀況的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-10-10
  • Java程序員需要掌握的英語(yǔ)詞組

    Java程序員需要掌握的英語(yǔ)詞組

    這篇文章主要為大家詳細(xì)匯總了Java程序員需要掌握的英語(yǔ)詞組 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Java三大特性之多態(tài)詳解

    Java三大特性之多態(tài)詳解

    多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦?。多態(tài): 是指同一行為,具有多個(gè)不同表現(xiàn)形式。本文將來和大家詳細(xì)說說Java中的多態(tài),需要的可以了解一下
    2022-10-10
  • 詳解Java中的線程模型與線程調(diào)度

    詳解Java中的線程模型與線程調(diào)度

    這篇文章主要介紹了詳解Java中的線程模型與線程調(diào)度的相關(guān)資料,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-02-02

最新評(píng)論

泰和县| 九龙县| 安仁县| 江安县| 乌拉特后旗| 长沙县| 阳曲县| 大宁县| 南丹县| 建水县| 凤翔县| 乐山市| 安顺市| 汨罗市| 什邡市| 泰和县| 皋兰县| 新宁县| 奉化市| 奎屯市| 龙山县| 沛县| 娱乐| 岳普湖县| 西和县| 谢通门县| 抚顺县| 正宁县| 阳谷县| 平泉县| 南溪县| 崇州市| 昌图县| 缙云县| 大埔县| 邯郸市| 武安市| 清原| 新巴尔虎左旗| 万州区| 黄石市|