亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Springboot中怎么實現多線程并發定時任務

發布時間:2022-02-25 15:04:40 來源:億速云 閱讀:421 作者:小新 欄目:開發技術

小編給大家分享一下Springboot中怎么實現多線程并發定時任務,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

一、實現

1、啟動類

在啟動類添加注解@EnableScheduling開啟,不然不起用做。

2、新建任務類

添加注解@Component注冊到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:定時任務
 * @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<>();

    /**
     * 默認啟動10個線程
     */
    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:初始化任務
     * 1、從數據庫獲取執行任務的集合【TxTask】
     * 2、通過調用 【refresh】 方法刷新任務列表
     * 3、每次數據庫中的任務發生變化后重新執行【1、2】
     * @author:tanyp
     * @dateTime:2020/7/23 21:37
     * @Params: [tasks]
     * @Return: void
     * @editNote:
     */
    public void refreshTask(List<MyTask> tasks) {
        // 刪除已經取消任務
        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;
                }
            });
        });

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

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

            // 任務執行時間發生了變化,則刪除該任務
            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() {
                    // 執行業務邏輯
                    try {
                        log.info("執行單個任務,任務ID【{}】執行規則【{}】", txTask.getTaskId(), txTask.getExpression());
                        System.out.println("==========================執行任務=============================");
                    } catch (Exception e) {
                        log.error("執行發送消息任務異常,異常信息:{}", e);
                    }
                }
            }, expression);
            ScheduledFuture<?> future = registrar.getScheduler().schedule(task.getRunnable(), task.getTrigger());
            cronTasks.put(txTask.getTaskId(), task);
            scheduledFutures.put(txTask.getTaskId(), future);
        });
    }

}

3、創建自啟動任務類

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:自啟動
 * @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("================項目啟動初始化定時任務====開始===========");
        /**
         * 初始化三個任務:
         * 1、10秒執行一次
         * 2、15秒執行一次
         * 3、20秒執行一次
         */
        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("================項目啟動初始化定時任務====完成==========");
    }
}

4、實體

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:任務實體
 * @author:tanyp
 * @dateTime:2020/7/23 21:41 
 * @editNote:
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyTask {

    /**
     * 任務id
     */
    private String taskId;

    /**
     * 任務執行規則時間
     */
    private String expression;
}

二、測試

初始化三個任務,分別為:

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

三、動態使用方式

1、啟動方式有兩種:

  • 啟動項目后,手動調用ScheduledTask.refreshTask(List tasks),并初始化任務列表;

  • 使用我測試中的方式,配置項目啟動完成后自動調用初始任務的方法,并初始化任務列表。

2、數據初始化

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

  • 根據業務需求修改MyTask實體類;

  • 這里的初始化數據可以從數據庫讀取數據賦值給集合;

例如:從mysql讀取任務配置表的數據,調用refreshTask()方法。

3、如何動態?

  • 修改:修改某一項正在執行的任務規則;

  • 添加:添加一項新的任務;

  • 刪除:停止某一項正在執行的任務。

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

怎么重新調用 refreshTask()方法:可以另外啟一個任務實時監控任務表的數據變化。

以上是“Springboot中怎么實現多線程并發定時任務”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

龙泉市| 抚宁县| 内黄县| 海伦市| 渑池县| 石泉县| 巨鹿县| 饶河县| 黎城县| 万山特区| 昭觉县| 连云港市| 延寿县| 邯郸县| 茶陵县| 徐水县| 青阳县| 和龙市| 永靖县| 崇义县| 嘉义市| 余姚市| 措勤县| 游戏| 漠河县| 团风县| 顺平县| 台南县| 尚志市| 黄大仙区| 铁岭市| 晋中市| 澄城县| 改则县| 大埔县| 西林县| 桐乡市| 延安市| 凤台县| 潼关县| 星子县|