首页 > 其他分享 >SpringBoot不用三方框架,怎么动态调度定时任务,ScheduledExecutorService 详解

SpringBoot不用三方框架,怎么动态调度定时任务,ScheduledExecutorService 详解

时间:2024-11-24 11:59:24浏览次数:6  
标签:SpringBoot interval 任务 详解 ScheduledExecutorService import 定时 public

文章目录

Spring Boot 提供了强大的定时任务支持,无需依赖任何第三方框架,即可轻松实现可配置的定时任务。通过使用 @EnableScheduling 注解启用定时任务支持后,我们可以利用 @Scheduled 注解来定义定时任务的方法,这些方法可以在指定的时间间隔或特定时间点自动执行。

我们还可以通过集成 ScheduledExecutorService 来实现灵活的定时任务管理。ScheduledExecutorService 是 Java 标准库的一部分,能够以固定速率或延迟执行任务,非常适合用于需要精确控制执行时机的场景。在 Spring Boot 应用中,可以将 ScheduledExecutorService 与 Spring 的 Bean 管理机制相结合,创建可配置的定时任务。

更重要的是,通过构建一个简单的 Web 控制台,用户可以直接从页面上对定时任务进行各种操作,包括但不限于开启或关闭特定任务、调整任务的执行频率等,从而实现了任务的动态管理和即时生效。这种方式不仅提升了系统的灵活性和响应速度,也为运维人员提供了极大的便利。

基础版:控制任务启动与停止

1. 创建定时任务

首先,使用@Scheduled注解来定义一个简单的定时任务。

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyScheduledTask {

    private volatile boolean enabled = true; // 定义一个开关来控制定时任务的执行
    private long interval = 5000; // 默认每5秒执行一次

    @Scheduled(fixedRateString = "${task.interval:5000}")
    public void performTask() {
        if (!enabled) {
            return;
        }
        // 执行具体的业务逻辑
        System.out.println("定时任务正在运行...");
    }

    // 提供setter方法,用于外部修改定时任务的状态
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void setInterval(long interval) {
        this.interval = interval;
    }
}

这里使用了fixedRateString属性,并从配置文件读取任务间隔时间。注意,这里我们还添加了一个enabled变量来控制任务是否应该被执行。

2. 配置Spring Boot以启用定时任务支持

确保在你的主应用类或配置类上添加@EnableScheduling注解,以便启用定时任务的支持。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

3. 创建控制器来管理定时任务

接下来,创建一个控制器来提供API接口,允许用户通过HTTP请求来控制定时任务的启停和调整执行频率。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired
    private MyScheduledTask myScheduledTask;

    @PostMapping("/toggle")
    public String toggleTask(@RequestParam Boolean enabled) {
        myScheduledTask.setEnabled(enabled);
        return "任务状态已更新为:" + (enabled ? "开启" : "关闭");
    }

    @PostMapping("/set-interval")
    public String setInterval(@RequestParam Long interval) {
        myScheduledTask.setInterval(interval);
        // 这里需要重启任务以应用新的间隔时间设置
        // 注意:Spring Boot本身不直接支持动态更改任务间隔时间,可能需要手动处理
        return "任务执行间隔已设置为:" + interval + " 毫秒";
    }
}

4. 处理动态调整任务间隔的问题

由于Spring Boot的@Scheduled注解并不支持动态更改任务间隔时间,因此如果需要动态调整间隔时间,你可能需要采取一些额外措施。一种可能的方法是取消当前的任务,并重新注册一个新的任务,或者使用ScheduledExecutorService来替代@Scheduled注解的功能。

对于更复杂的场景,考虑使用ScheduledExecutorService来自定义定时任务,这样可以更加灵活地控制任务的执行。

5. 测试你的API

启动你的Spring Boot应用后,你可以通过发送HTTP POST请求到/task/toggle/task/set-interval来测试这些API是否按预期工作。

进阶版:动态调整任务执行频率

在Spring Boot中使用ScheduledExecutorService来实现定时任务,可以提供更多的灵活性,例如动态调整任务的执行频率。下面是一个详细的步骤指南,展示如何在Spring Boot中集成ScheduledExecutorService并创建可配置的定时任务。

1. 添加依赖

确保你的项目已经包含了Spring Boot的Web Starter依赖,因为我们将通过REST API来控制定时任务。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 创建定时任务服务

首先,创建一个服务类来管理定时任务。在这个类中,我们将使用ScheduledExecutorService来调度任务。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class TaskSchedulerService {

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    private volatile boolean enabled = true;
    private long interval = 5000; // 默认每5秒执行一次

    @Value("${task.initialDelay:0}")
    private long initialDelay;

    @PostConstruct
    public void init() {
        scheduleTask();
    }

    @PreDestroy
    public void destroy() {
        scheduler.shutdownNow();
    }

    private void scheduleTask() {
        scheduler.scheduleAtFixedRate(() -> {
            if (enabled) {
                performTask();
            }
        }, initialDelay, interval, TimeUnit.MILLISECONDS);
    }

    private void performTask() {
        // 执行具体的业务逻辑
        System.out.println("定时任务正在运行...");
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void setInterval(long interval) {
        this.interval = interval;
        // 重新调度任务以应用新的间隔时间
        scheduler.shutdownNow();
        scheduleTask();
    }
}

3. 创建控制器来管理定时任务

接下来,创建一个控制器来提供API接口,允许用户通过HTTP请求来控制定时任务的启停和调整执行频率。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/task")
public class TaskController {

    @Autowired
    private TaskSchedulerService taskSchedulerService;

    @PostMapping("/toggle")
    public String toggleTask(@RequestParam Boolean enabled) {
        taskSchedulerService.setEnabled(enabled);
        return "任务状态已更新为:" + (enabled ? "开启" : "关闭");
    }

    @PostMapping("/set-interval")
    public String setInterval(@RequestParam Long interval) {
        taskSchedulerService.setInterval(interval);
        return "任务执行间隔已设置为:" + interval + " 毫秒";
    }
}

4. 配置Spring Boot应用

确保在你的主应用类或配置类上添加必要的注解,以启用组件扫描。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5. 测试你的API

启动你的Spring Boot应用后,你可以通过发送HTTP POST请求来测试这些API:

  • 启动或停止任务:

    POST /task/toggle?enabled=true
    
  • 设置任务执行间隔:

    POST /task/set-interval?interval=10000
    

6. 注意事项

  • 线程池大小:根据你的应用场景选择合适的线程池大小。如果任务较多或任务执行时间较长,可能需要增加线程池的大小。
  • 异常处理:在performTask方法中添加适当的异常处理逻辑,以防止某个任务的失败影响整个调度器。
  • 任务取消:在调用shutdownNow方法时,可能会有任务正在执行,需要确保这些任务能够安全地终止。

ScheduledExecutorService 详解

ScheduledExecutorService 是 Java 并发库中的一个重要接口,用于管理和调度定时任务。它扩展了 ExecutorService 接口,提供了更多与定时任务相关的功能。下面是对 ScheduledExecutorService 的详细讲解,包括其主要方法、使用示例以及注意事项。

1. ScheduledExecutorService 概述

ScheduledExecutorService 是一个特殊的 ExecutorService,它可以用来安排命令在未来某个时间点执行,支持定期执行任务。常见的实现类有 ScheduledThreadPoolExecutorSingleThreadScheduledExecutor

2. 主要方法

ScheduledExecutorService 提供了以下几个主要方法来调度任务:

2.1 schedule(Runnable command, long delay, TimeUnit unit)
  • 参数
    • command:要执行的任务。
    • delay:首次执行任务前的延迟时间。
    • unit:延迟时间的单位。
  • 返回值ScheduledFuture<?>,表示任务的未来结果。
2.2 schedule(Callable<V> callable, long delay, TimeUnit unit)
  • 参数
    • callable:要执行的任务,该任务可以返回一个结果。
    • delay:首次执行任务前的延迟时间。
    • unit:延迟时间的单位。
  • 返回值ScheduledFuture<V>,表示任务的未来结果。
2.3 scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
  • 参数
    • command:要执行的任务。
    • initialDelay:首次执行任务前的延迟时间。
    • period:两次连续执行之间的固定周期。
    • unit:时间单位。
  • 返回值ScheduledFuture<?>,表示任务的未来结果。
2.4 scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
  • 参数
    • command:要执行的任务。
    • initialDelay:首次执行任务前的延迟时间。
    • delay:每次执行完成后到下一次执行开始的固定延迟。
    • unit:时间单位。
  • 返回值ScheduledFuture<?>,表示任务的未来结果。

3. 使用示例

3.1 单次延迟执行任务
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SingleExecutionExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        Runnable task = () -> System.out.println("任务执行了");

        // 延迟5秒后执行任务
        scheduler.schedule(task, 5, TimeUnit.SECONDS);

        // 关闭调度器
        scheduler.shutdown();
    }
}
3.2 定期执行任务
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class PeriodicExecutionExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        Runnable task = () -> System.out.println("任务执行了");

        // 延迟2秒后开始执行,之后每3秒执行一次
        scheduler.scheduleAtFixedRate(task, 2, 3, TimeUnit.SECONDS);

        // 模拟长时间运行
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 关闭调度器
        scheduler.shutdown();
    }
}
3.3 动态调整任务间隔
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DynamicIntervalExample {
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private volatile boolean enabled = true;
    private long interval = 5000; // 默认每5秒执行一次

    public void start() {
        scheduleTask();
    }

    private void scheduleTask() {
        scheduler.scheduleAtFixedRate(() -> {
            if (enabled) {
                performTask();
            }
        }, 0, interval, TimeUnit.MILLISECONDS);
    }

    private void performTask() {
        System.out.println("任务执行了");
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public void setInterval(long interval) {
        this.interval = interval;
        // 重新调度任务以应用新的间隔时间
        scheduler.shutdownNow();
        scheduleTask();
    }

    public static void main(String[] args) {
        DynamicIntervalExample example = new DynamicIntervalExample();
        example.start();

        // 模拟动态调整间隔
        try {
            Thread.sleep(10000);
            example.setInterval(2000); // 将间隔时间改为2秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 模拟长时间运行
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 关闭调度器
        example.scheduler.shutdown();
    }
}

4. 注意事项

  • 线程池大小:根据任务的数量和执行时间选择合适的线程池大小。如果任务较多或执行时间较长,建议增加线程池的大小。
  • 异常处理:在任务执行过程中可能会抛出异常,需要在任务代码中添加适当的异常处理逻辑,以防止某个任务的失败影响整个调度器。
  • 任务取消:可以使用 ScheduledFuture.cancel(true) 方法来取消任务。如果任务已经在执行中,true 参数会尝试中断正在执行的任务。
  • 资源释放:在不再需要调度器时,应调用 shutdown()shutdownNow() 方法来释放资源。

标签:SpringBoot,interval,任务,详解,ScheduledExecutorService,import,定时,public
From: https://blog.csdn.net/qq_41089021/article/details/143977555

相关文章

  • SpringBoot框架:在线课程管理的技术突破
    4系统概要设计4.1概述本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示:图4-1系统工作原理图4.2系统结构本系统......
  • Suricata 技术详解
    Suricata并非是黑客工具,而是一款开源的高效网络威胁检测与防御工具,以下为你展开介绍: 功能特性入侵检测与防御:Suricata能够作为网络入侵检测系统(IDS),实时监控网络流量,对可疑活动和入侵行为发出警报。同时,它也可以充当入侵防御系统(IPS),检测到恶意活动和流量后直接进行阻断,有效......
  • 经典战法【均线老鸭头】战法的机构构成,集中模型以及买卖操盘技术,技术要点图文详解
    直接上干货,首先【均线老鸭头】战法的均线构成我们选择5-10-60均线三条。老鸭头名称的由来,这是一个形象的说法,如上图,图中均线系统排列的形态,是不是像一个鸭脑袋?第一段上涨是鸭脖子,股价开始回落处画上一个圆圈,是鸭子的眼睛,第三段启动上涨的位置就是鸭子的嘴巴。整个图形合在一......
  • 基于SpringBoot + Vue的汽车配件销售管理系统设计与实现(源码+文档+部署)
    文章目录1.前言2.系统演示录像3.论文参考4.代码运行展示图5.技术框架5.1SpringBoot技术介绍5.2Vue技术介绍6.可行性分析7.系统测试7.1系统测试的目的7.2系统功能测试8.数据库表设计9.代码参考10.数据库脚本11.找我做程序,有什么保障?12.联系我们1.前......
  • 基于SpringBoot + Vue的儿童图书推荐系统设计与实现(源码+文档+部署)
    文章目录1.前言2.系统演示录像3.论文参考4.代码运行展示图5.技术框架5.1SpringBoot技术介绍5.2Vue技术介绍6.可行性分析7.系统测试7.1系统测试的目的7.2系统功能测试8.数据库表设计9.代码参考10.数据库脚本11.找我做程序,有什么保障?12.联系我们1.前......
  • SpringBoot技术驱动的在线课程平台
    1系统概述1.1研究背景随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理在线课程管理系统的相关信息成为必然。开发合适的在线课程管理系统,可以方便管理人员对在线......
  • 基于Springboot演出服装在线租赁网站设计与实现(作品+论文+开题报告)
      博主介绍:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育、辅导。所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩,提供核心代码讲解,答辩指导。项目配有对应开......
  • 基于java ssm springboot留守儿童爱心网站系统旧物爱心捐赠志愿者活动报名(源码+文档+
     文章目录系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈后端框架springboot前端框架vue持久层框架MyBaitsPlus系统测试四、代码参考源码获取目的摘要: 本文介绍了基于JavaSSM和SpringBoot构建的留守儿童爱心网站系统。该系统旨在为留守......
  • 基于java ssm springboot校园二手书交易管理系统二手图书商城(源码+文档+运行视频+讲解
     文章目录系列文章目录目的前言一、详细视频演示二、项目部分实现截图三、技术栈后端框架springboot前端框架vue持久层框架MyBaitsPlus系统测试四、代码参考源码获取目的摘要: 本文介绍了基于JavaSSM和SpringBoot构建的校园二手书交易管理系统。该系统为校园内......
  • 基于Java+SpringBoot+Vue+HTML5校园闲置物品租售系统(源码+LW+调试文档+讲解等)/校园
    博主介绍......