Springboot使用ThreadPoolTaskScheduler轻量级多线程定时任务框架

news2024/9/21 17:34:58

简介: Spring注解定时任务使用不是很灵活,如果想要灵活的配置定时任务,可以使用xxl-job 或者 quartz等定时任务框架,但是过于繁琐,可能成本较大。所以可以使用ThreadPoolTaskScheduler来灵活处理定时任务

ThreadPoolTaskScheduler是什么

ThreadPoolTaskScheduler 是 Spring Framework 中的一部分,主要用于调度任务。它基于线程池,可以处理异步任务和定时任务

主要api

  • schedule(Runnable task, Trigger trigger) corn表达式,周期执行
  • schedule(Runnable task, Date startTime) 定时执行
  • scheduleAtFixedRate(Runnable task, Date startTime, long period)
    定时周期间隔时间执行。间隔时间单位 TimeUnit.MILLISECONDS
  • scheduleAtFixedRate(Runnable task, long period) 间隔时间以固定速率执行。单位毫秒

固定速率执行不会管上次执行的状态如何

在使用前需要配置下ThreadPoolTaskScheduler

@Configuration
public class SchedulingTaskConfig {

    @Bean(name = "myThreadPoolTaskScheduler")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(60);
        taskScheduler.setThreadNamePrefix("task-");
        taskScheduler.setAwaitTerminationSeconds(3000);
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        return taskScheduler;
    }
}

cron表达式


   @Override
    public String startTask() {
     ScheduledFuture<?> schedule = myThreadPoolTaskScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("1s执行一次");
            }
        }, new CronTrigger("0/1 * * * * ?"));
    

定时执行一次

 myThreadPoolTaskScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("定时执行3s后开始执行");
            }
        },new Date(System.currentTimeMillis() + 3000));

在固定时间以固定速率执行

 myThreadPoolTaskScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("定时执行3s后开始执行,固定3s执行一次");
            }
        },new Date(System.currentTimeMillis() + 3000),3000);

任务取消

private  ScheduledFuture<?> schedule ;
    @Override
    public String startTask() {

         schedule = myThreadPoolTaskScheduler.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("定时执行3s后开始执行,固定3s执行一次");
            }
        }, new Date(System.currentTimeMillis() + 3000), 3000);

        return "开启成功";
    }

    @Override
    public String stopTask() {
        if (schedule != null){
            schedule.cancel(true);
             System.out.println("任务取消成功");
            return "取消成功";
        }
        return "取消失败";
    }

实现页面控制定时任务开关

将定时任务保存到数据库中,并在页面上实现定时任务的开关,以及更新定时任务时间后重新创建定时任务

数据库实体




@TableName("task")
@Data
public class ScheduleTask {
    public interface Update{};

    @TableId(type = IdType.AUTO)
    @NotNull(message = "任务id不能为空",groups = Update.class)
    private Integer id;

    @NotBlank(message = "请填写任务执行类")
    @TableField("task_clazz")
    private String taskClazz;

    @NotBlank(message = "请填写任务执行方法")
    @TableField("task_method")
    private String taskMethod;

    @NotBlank(message = "请填写任务执行时间,采用cron格式")
    @TableField("cron")
    private String cron;

    @TableLogic
    @TableField("status")
    private Integer status;
}

contrloller

@RestController
@RequiredArgsConstructor
public class TaskManagerController {


    private final TaskManagerService taskManagerService;

    @PostMapping("/addTask")
    public Boolean addTask(@RequestBody @Validated ScheduleTask task){
        return taskManagerService.addTask(task);
    }

    @PostMapping("/stopTask/{id}")
    public Boolean stopTask(@PathVariable Integer id){
        return taskManagerService.stopTask(id);
    }
}

service



@Service
@Slf4j
@RequiredArgsConstructor
public class TaskManagerServiceImpl implements TaskManagerService {


    private final ScheduleTaskMapper scheduleTaskMapper;
    private final TaskManager taskManager;
    @Override
    public Boolean addTask(ScheduleTask task) {
        int i = scheduleTaskMapper.insert(task);
        if (i > 0){
            TaskRunnable taskRunnable = new TaskRunnable(task.getTaskClazz(), task.getTaskMethod());
            taskManager.addTask(String.valueOf(task.getId()),taskRunnable,task.getCron());
            return true;
        }
        return false;
    }

    @Override
    public Boolean stopTask(Integer id) {
        int i = scheduleTaskMapper.deleteById(id);
        if (i> 0){
            taskManager.stopTask(String.valueOf(id));
            return true;
        }
        return false;
    }
}

TaskRunnable

通过此类获取具体的执行方法



@Slf4j
public class TaskRunnable implements Runnable{
    /**
     * 定时任务类
     */
    private final String clazz;

    /**
     * 定时任务方法
     */
    private final String methodName;

    public TaskRunnable(String clazz, String methodName) {
        this.clazz = clazz;
        this.methodName = methodName;
    }

    @Override
    public void run() {

        try {
            //获取类
            Object bean = SpringContextUtils.getBean(clazz);
            //获取方法
           Method method = bean.getClass().getDeclaredMethod(methodName);
           //设置方法可用
           ReflectionUtils.makeAccessible(method);
           //执行方法
           method.invoke(bean);
        } catch (Exception e) {
            log.error("获取方法信息报错:{}",e.getMessage());
            throw new RuntimeException(e);
        }
    }
}

任务调度类



@Component
@RequiredArgsConstructor
@Slf4j
public class TaskManager {

    private final ThreadPoolTaskScheduler myThreadPoolTaskScheduler;

    public static ConcurrentHashMap<String, ScheduledFuture<?>> cache = new ConcurrentHashMap<>();

    /**
     * 创建定时任务
     * @param key 任务key
     * @param taskRunnable 当前线程
     * @param cron 定时任务cron
     */
    public void addTask(String key ,TaskRunnable taskRunnable ,String cron){
        //取消任务
        this.stopTask(key);
        ScheduledFuture<?> schedule = myThreadPoolTaskScheduler.schedule(taskRunnable, new CronTrigger(cron));
        if (schedule != null){
            cache.put(key,schedule);
            log.info("当key为{}的定时任务创建成功",key);
        }
    }


    public void stopTask(String key){
        if (cache.get(key) == null){
            log.info("当前没有key为{}的定时任务",key);
            return;
        }
        ScheduledFuture<?> scheduledFuture = cache.get(key);
        if (scheduledFuture != null){
            scheduledFuture.cancel(true);
            cache.remove(key);
            log.info("当前key为{}的定时任务已取消",key);
        }

    }
}

工具类




@Component
public class SpringContextUtils implements ApplicationContextAware {
    private static ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtils.context = applicationContext;
    }

    public static Object getBean(String name){
        return context.getBean(name);
    }
}

方法测试


@Slf4j
@Component(value = "testTask")
public class TestTask {

    public void taskMethod(){
        log.info(String.format("调用了当前定时任务"));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2152908.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能开发实战辅助诊断应用解析

内容导读 项目分析预备知识项目实战 一、项目分析 1、提出问题 随着人们生活水平的提升和健康意识的增强&#xff0c;民众定期进行身体健康体检已成为常态&#xff0c;这种早期的疾病检测和筛查可以及早发现身体里已经出现的异常体征信息&#xff0c;做出正确诊断和有效处理…

分布式系统的概念与设计模式

概念 定义&#xff1a;分布式系统是指将数据和计算任务分散到多个独立的计算机上&#xff0c;这些计算机通过网络进行通信和协作&#xff0c;共同对外提供服务。分布式系统不仅提高了系统的可靠性和可扩展性&#xff0c;还增强了系统的并发处理能力和数据管理能力。 特点&…

内存:生成式AI带来全新挑战与机遇

之前小编也写过多篇AI存储相关的文章&#xff0c;包括AI背景与分层存储的分析&#xff0c;以及AI存储重点从训练转向推理等内容。具体参考&#xff1a; 深度剖析&#xff1a;AI存储架构的挑战与解决方案 存储正式迈入超大容量SSD时代&#xff01; 这可能是最清晰的AI存储数据…

多线程篇七

多线程篇七 若笔者理解有误&#xff0c;欢迎交流指正⭐ 定时器 什么是定时器 听到定时器&#xff0c;首先想到的是“闹钟”.到一个设置好的时间之后就执行某个指定好的代码.(在实际开发中非常常用&#xff0c;如网络通信【邮件发送】) 你在抢演唱会门票&#xff0c;已经到了…

使用madExcept检测内存泄漏

代码异常堆栈跟踪&#xff1a;Mad Except 一、安装 官网 运行&#xff0c;选择madExcept5然后安装。 输入yes继续 二、使用 新建一个VCL项目 在project中多了一项设置 选择OK后会发现项目多了几个引用单元。 此时运行程序&#xff0c;再退出&#xff0c;会显示没有任何内存…

prober found high clock drift,Linux服务器时间不能自动同步,导致服务器时间漂移解决办法。

文章目录 一、场景二、问题三、解决办法&#xff08;一&#xff09;给服务器添加访问网络能力&#xff08;二&#xff09;手动同步1. 检查有没有安装ntp2. 没有安装ntp则离线安装ntp2.1 下载安装包2.2 安装2.3 启动 ntp 3. 设置内部时钟源3.1 编辑/etc/ntp.conf3.1 重启ntp服务…

2010-2020年全国30个省以GDP为核心的区域经济韧性数据(含原始数据+代码+结果)

2010-2020年全国30个省以GDP为核心的区域经济韧性数据(含原始数据代码结果) 1、时间&#xff1a;2010-2022年 2、来源&#xff1a;统计年鉴、各省年鉴、国家统计局 3、指标&#xff1a;地区生产总值 4、范围&#xff1a;30省 5、参考文献&#xff1a; 数字经济及其内部耦…

页面关键路径渲染详解

关键路径渲染 浏览器不会等待全部资源都下载完后才进行渲染&#xff0c;而是采用渐进式的渲染方式&#xff0c;本文就介绍一下这种渐进式的渲染方式。 当浏览器获取到用于呈现网页的资源后&#xff0c;通常就会开始渲染网页。那么究竟是在什么时候就会开始渲染&#xff1f; …

Visual Studio 2022 - QT 环境中文字符乱码问题

Visual Studio 2022 - QT 环境中文字符乱码问题 一、Visual Studio 2022 - Qt 环境 在 QT 中使用中文字符串常会出现乱码现象&#xff0c;如下&#xff1a;以下提供了几个解决方法&#xff0c;仅供参考 QString str "百香果真是一直可爱的小猫咪"; qDebug() <…

RK3568笔记六十:V4L2命令测试

若该文为原创文章,转载请注明原文出处。 测试V4L2是想移植韦老师的相机程序,但他使用的是V4L2方式采集摄像头。 而正点原子的rknn使用的是opencv。 这里记录测试过程 一、常用调试命令 1、抓取图像 使用 v4l2-ctl 抓取一帧图像:v4l2-ctl -d /dev/video0 --set-fmt-video…

EmptyDir-数据存储

1.EmptyDir EmptyDir是最基础的Volume类型&#xff0c;一个EmptyDir就是Host上的一个空目录。 EmptyDir是在Pod被分配到Node时创建的&#xff0c;它的初始内容为空&#xff0c;并且无须指定宿主机上对应的目录文件&#xff0c;因为kubernetes会自动分配一个目录&#xff0c;当…

vulnhub(12):bob 1.0.1(gpg文件解密)

端口 nmap主机发现 nmap -sn 192.168.72.0/24 ​ Nmap scan report for 192.168.72.169 Host is up (0.00020s latency). ​ 169是新出现的机器&#xff0c;他就是靶机 nmap端口扫描 nmap -Pn -sV 192.168.72.169 -p- --min-rate 10000 -oA nmap/scan 扫描开放端口保存到 nmap…

【Verilog学习日常】—牛客网刷题—Verilog快速入门—VL17

用3-8译码器实现全减器 描述 请使用3-8译码器和必要的逻辑门实现全减器&#xff0c;全减器接口图如下&#xff0c;A是被减数&#xff0c;B是减数&#xff0c;Ci是来自低位的借位&#xff0c;D是差&#xff0c;Co是向高位的借位。 3-8译码器代码如下&#xff0c;可将参考代码添…

论文阅读:Omni-Kernel Network for Image Restoration

论文地址&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/27907 项目地址&#xff1a;https://github.com/c-yn/OKNet 发表时间&#xff1a;2024 图像恢复的目的是从一个退化的低质量的观测中重建一个高质量的图像。最近&#xff0c;Transformer模型由于其强大…

upx魔改壳大全

一&#xff0c;ELF程序 &#xff08;一&#xff09;overlay_offset被修改 将此标志修改为正确的***F4 00 00 00***即可用工具正常脱壳 二&#xff0c;EXE程序 &#xff08;一&#xff09;upx标志位被修改 将三个错误标志修改为正确的***UPX0***UPX1***UPX!***即可用工具正常…

利用JAVA写一张纸折叠珠穆拉玛峰高度

public class zhumulama {public static void main(String[] args) {double height 8848860;double zhi 0.1;int count 0;while(zhi < height){zhi*2;//每次折完厚度count;//计数}System.out.println("一共需要折"count"次");System.out.println(&qu…

灵当CRM系统index.php存在SQL注入漏洞

文章目录 免责申明漏洞描述搜索语法漏洞复现nuclei修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 灵当CRM系统是一款功能全面、易于使用的客户关系管理&#xff08;C…

C++ ——日期类的实现和注释浅解

目录 日期类实现 1. 日期天数 2. 日期天数 3. 日期-天数 3.1 日期-天数 4. 比较运算符 5. 日期-日期 6. 代码汇总 Date.h Date.cpp Test.cpp 日期类实现 1. 日期天数 // d1 100 //可以改变d1&#xff0c;所以可以直接相加 Date& Date::operator(int day) {//如…

2024年中国研究生数学建模竞赛F题思路代码模型文章——X射线脉冲星光子到达时间建模

2024年中国研究生数学建模竞赛F题 X射线脉冲星光子到达时间建模 脉冲星&#xff08;Pulsar&#xff09;是高速自转的中子星&#xff0c;具有体积小、密度大的特征。脉冲星的高速自转会形成脉冲&#xff0c;而脉冲的周期其实就是脉冲星的自转周期 。在旋转过程中&#xff0c;脉…

2024年华为杯研赛(B题)数学建模竞赛解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…