SpringBoot中实现定时任务(Quartz)(一)

简介: SpringBoot中实现定时任务(Quartz)

一、使用Spring Task

Spring 3.0以后自带了 task 调度工具,使用比 Quartz简单方便,使用 @Scheduled 注解。

1、创建一个 SpringBoot项目,引入spring-boot-starter-web依赖。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
  1. 在启动类上添加 @EnableScheduling 注解,表示开启定时任务。


@SpringBootApplication
@EnableScheduling
public class QuartzApplication {
    public static void main(String[] args) {
        SpringApplication.run(QuartzApplication.class, args);
    }
}
  1. 了解 @Scheduled 注解

在方法上使用 @Scheduled 注解表示开启一个定时任务:下面参数单位都是毫秒

  • fixedRate:表示按一定频率来执行定时任务,具体是指两次任务的开始时间间隔,即第二次任务开始时,第一次任务可能还没结束。
  • fixedDelay:表示按一定时间间隔来执行定时任务,具体是指本次任务结束到下次任务开始之间的时间间隔。该属性还可以配合initialDelay使用, 定义该任务延迟执行时间。
  • initialDelay:表示首次任务启动的延迟时间。与fixedDelay配合使用。
  • cron:通过 cron 表达式来配置任务执行时间,cron 表达式格式为:[秒] [分] [小时] [日] [月] [周] [年]

2、单线程执行任务

使用同一个线程中串行执行,如果只有一个定时任务,这样做肯定没问题,当定时任务增多,如果一个任务卡死,会导致其他任务也无法执行。

  1. 创建一个类,配置定时任务


@Component
public class Task1 {
    @Scheduled(fixedRate = 2000)
    public void fixedRateTask() {
        System.out.println("fixedRateTask定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Scheduled(fixedDelay = 2000)
    public void fixedDelayTask1() {
        System.out.println("fixedDelayTask1111定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Scheduled(initialDelay = 2000,fixedDelay = 2000)
    public void initialDelayTask2() throws InterruptedException {
        System.out.println("initialDelayTask2222定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(15);
    }
    @Scheduled(cron = "0/5 * * * * ?")
    public void cron() {
        System.out.println("cron定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
}
  1. 启动项目,定时任务就开始工作了
  • 可以看到使用的是同一个线程,并出现了任务阻塞的情况。

image.png

3、多线程执行任务

Spring Task 默认是单线程的,想要改成多线程,

给Spring Task提供一个多线程的TaskScheduler,Spring已经有默认实现。

  1. 方式一

创建配置类,@EnableAsync注解:表示开启异步事件的支持


@Configuration
@EnableAsync // 开启异步事件的支持
public class AsyncTaskConfig {
    private int corePoolSize = 10;
    private int maxPoolSize = 200;
    private int queueCapacity = 10;
    @Bean
    public Executor taskExecutor() {
        // 线程池
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.initialize();
        return executor;
    }
}

在定时任务的类或者方法上添加 @Async 注解。最后重启项目,每一个任务都是在不同的线程中

image.png

  1. 方式二

创建配置类


@Configuration
@EnableAsync // 开启异步事件的支持
public class ScheduleConfig {
    @Bean("taskScheduler1")
    public TaskScheduler taskScheduler1(){
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("spring-task1-thread");
        return scheduler;
    }
    @Bean
    public TaskScheduler taskScheduler2(){
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(10);
        scheduler.setThreadNamePrefix("spring-task2-thread");
        return scheduler;
    }
}

在定时任务的类或者方法上添加 @Async 注解。最后重启项目。


@Component
public class TestTask2 {
    @Async("taskScheduler1")
    @Scheduled(cron = "0/1 * * * * ?")
    public void execute1() {
        System.out.println("execute1定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Async("taskScheduler2")
    @Scheduled(cron = "0/1 * * * * ?")
    public void execute2() throws InterruptedException {
        System.out.println("execute2定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Async("taskScheduler2")
    @Scheduled(cron = "0/1 * * * * ?")
    public void execute3() throws InterruptedException {
        System.out.println("execute3定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Scheduled(cron = "0/2 * * * * ?")
    public void execute4() throws InterruptedException {
        System.out.println("execute4定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
    }
    @Scheduled(cron = "0/3 * * * * ?")
    public void execute5() throws InterruptedException {
        System.out.println("execute5定时任务开始 : " + LocalDateTime.now().toLocalTime() + ",线程:" + Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(15);
    }
}

任务使用同上,线程池有区别。

image.png

二、使用第三方框架 Quartz

使用 @Scheduled 注解来解决简单的定时任务,大部分项目中可能都是使用 Quartz 来做定时任务。

Quartz是一个开源项目,专注于任务调度器,功能强大,提供了极为广泛的特性如持久化任务,集群和分布式任务等。 Quartz核心是调度器,还采用多线程管理。

  • 持久化任务:当应用程序停止运行时,所有调度信息不被丢失,当你重新启动时,调度信息还存在,这就是持久化任务。
  • 集群和分布式处理:当在集群环境下,当有配置Quartz的多个客户端(节点)时,

采用Quartz的集群和分布式处理时,简单了解几点

  • 1)一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。
  • 2)Quartz调度是通过触发器的类别来识别不同的任务,在不同的节点定义相同的触发器的类别,这样在集群下能稳定的运行,一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。
  • 3)分布式 体现在 当相同的任务定时在一个时间点,在那个时间点,不会被两个节点同时执行。

1、添加 Quartz 依赖

在 上面的 SpringBoot项目(把@Scheduled相关的注释掉)中使用 Quartz ,添加 Quartz 依赖。


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

在启动类上添加 @EnableScheduling 注解,表示开启定时任务。


@SpringBootApplication
@EnableScheduling
public class QuartzApplication {
    public static void main(String[] args) {
        SpringApplication.run(QuartzApplication.class, args);
    }
}

2、Quartz的使用

Quartz 在使用过程中,有两个关键概念,

  • 一个是 JobDetail(要做的事情),要定义 JobDetail,需要先自定义Job
  • 一个是 Trigger触发器(什么时候做)

1. 定义 Job


@Service
public class UserService {
    public String get(Long id){
        return "UserService get data:" + id;
    }
}


SpringBoot中实现定时任务(Quartz)(二)https://developer.aliyun.com/article/1393277

相关文章
|
7月前
|
druid Java 数据库
Spring Boot的定时任务与异步任务
Spring Boot的定时任务与异步任务
|
7月前
|
Java 调度 Spring
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
SpringBoot实现多线程定时任务动态定时任务配置文件配置定时任务
697 0
|
4月前
|
Java 关系型数据库 MySQL
SpringBoot 集成 Quartz + MySQL
SpringBoot 集成 Quartz + MySQL
122 1
|
5月前
|
SQL Java 调度
实时计算 Flink版产品使用问题之使用Spring Boot启动Flink处理任务时,使用Spring Boot的@Scheduled注解进行定时任务调度,出现内存占用过高,该怎么办
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
消息中间件 设计模式 Java
SpringBoot+Schedule 定时任务的配置开关
SpringBoot+Schedule 定时任务的配置开关
183 0
SpringBoot+Schedule 定时任务的配置开关
|
6月前
|
监控 Java 调度
Spring Boot中的定时任务调度
Spring Boot中的定时任务调度
|
6月前
|
SQL API 调度
Springboot2.4.5集成Quartz实现动态任务数据持久化-不怕重启服务
Springboot2.4.5集成Quartz实现动态任务数据持久化-不怕重启服务
265 0
|
6月前
|
Java API 调度
Web后端Javaee企业级开发之定时任务 Springboot整合任务框架Quartz和Task详解
Web后端Javaee企业级开发之定时任务 Springboot整合任务框架Quartz和Task详解
90 0
|
7月前
|
存储 数据可视化 安全
Java全套智慧校园系统源码springboot+elmentui +Quartz可视化校园管理平台系统源码 建设智慧校园的5大关键技术
智慧校园指的是以物联网为基础的智慧化的校园工作、学习和生活一体化环境,这个一体化环境以各种应用服务系统为载体,将教学、科研、管理和校园生活进行充分融合。无处不在的网络学习、融合创新的网络科研、透明高效的校务治理、丰富多彩的校园文化、方便周到的校园生活。简而言之,“要做一个安全、稳定、环保、节能的校园。
116 6
|
7月前
|
Java Spring 容器
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
SpringBoot 使用Quartz执行定时任务对象时无法注入Bean问题
275 1
下一篇
DataWorks