SpringBoot定时调度之Timer与Quartz详解

 更新时间:2023年06月18日 11:19:12   作者:莫念Program  
Java 中常用的定时调度框架有以下几种:Timer、ScheduledExecutorService、Spring Task和Quartz,本文主要来和大家讲讲他们的具体使用,需要的可以参考一下

Java 中常用的定时调度框架有以下几种:

  • Timer:Java 标准库中提供的一个定时调度工具,可以在指定的时间点或时间间隔内执行任务。Timer 的缺点是不支持并发执行和错误处理机制较弱。
  • ScheduledExecutorService:Java 标准库中提供的另一个定时调度工具,也可以在指定的时间点或时间间隔内执行任务。与 Timer 相比,ScheduledExecutorService 支持并发执行和错误处理机制较强。
  • Spring Task:Spring 框架中提供的一个定时调度工具,可以用于执行定时任务、异步任务等。Spring Task 支持多种时间表达式、动态调整和错误处理机制。
  • Quartz:一个用于定时调度的开源框架,可以在指定的时间点或时间间隔内自动执行任务。Quartz 支持多种配置方式和调度策略,功能丰富、灵活性高、易于集成并且可靠性较高。

Timer

Timer 是 Java 标准库中提供的一个定时调度工具,可以在指定的时间点或时间间隔内执行任务。Timer 提供了多种调度方式和执行策略,可以用于管理简单的定时任务。

Timer 使用 TimerTask 类来表示要执行的任务,TimerTask 是一个抽象类,需要继承并实现 run() 方法来定义具体的任务逻辑。Timer 还提供了多种调度方式,包括定时调度、周期性调度等。

以下是一个简单的 Timer 示例:

import java.util.Timer;
import java.util.TimerTask;
public class MyTask extends TimerTask {
    public void run() {
        System.out.println("定时任务执行了!");
    }
    public static void main(String[] args) {
        Timer timer = new Timer();
        MyTask task = new MyTask();
        timer.schedule(task, 5000); // 5秒后执行任务
    }
}

在上述代码中,我们定义了一个名为 MyTask 的 TimerTask 类,并在其中实现了 run() 方法来定义具体的任务逻辑。然后,在 main() 方法中创建了一个 Timer 实例,并使用 schedule() 方法来指定任务的执行时间和执行方式。

需要注意的是,Timer 的缺点是不支持并发执行和错误处理机制较弱。如果需要实现复杂的定时任务,可以考虑使用其它的定时调度框架,例如 Quartz、ScheduledExecutorService 等。

ScheduledExecutorService

ScheduledExecutorService 基于 Executor 框架,使用 ThreadPoolExecutor 来实现任务的执行和管理。

好的,下面是一个使用 ScheduledExecutorService 实现每天凌晨1点执行任务的示例:

import java.time.LocalTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MyTask implements Runnable {
    public void run() {
        System.out.println("定时任务执行了!当前时间:" + LocalTime.now());
    }
    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        MyTask task = new MyTask();
        long initialDelay = calculateInitialDelay();
        executor.scheduleAtFixedRate(task, initialDelay, 24, TimeUnit.HOURS); // 每天凌晨1点执行任务
    }
    private static long calculateInitialDelay() {
        LocalTime now = LocalTime.now();
        LocalTime target = LocalTime.of(1, 0, 0); // 目标执行时间为每天凌晨1点
        if (now.isBefore(target)) {
            return Duration.between(now, target).toMillis();
        } else {
            return Duration.between(now, target.plusDays(1)).toMillis();
        }
    }
}

在上述代码中,我们定义了一个名为 MyTask 的 Runnable 类,并在其中实现了 run() 方法来定义具体的任务逻辑。然后,在 main() 方法中创建了一个 ScheduledExecutorService 实例,并使用 scheduleAtFixedRate() 方法来指定任务的执行时间和执行方式。

为了实现每天凌晨1点执行任务,我们先定义了一个 calculateInitialDelay() 方法来计算任务的初始延迟时间。该方法会根据当前时间和目标执行时间计算出初始延迟时间,如果当前时间早于目标执行时间,则将初始延迟时间设置为两者时间差,否则将初始延迟时间设置为两者时间差加上一天的时间差。

最后,我们使用 scheduleAtFixedRate() 方法来指定任务的执行时间和执行周期,其中 initialDelay 参数为初始延迟时间,period 参数为执行周期,这里是每24小时执行一次。

需要注意的是,为了获取当前时间和计算时间差,我们使用了 Java 8 中的 LocalDate、LocalTime 和 Duration 类。如果使用的是 Java 7 或更早的版本,可以使用 Date、Calendar 等类来代替。

Spring Task

Spring Task(也称为 Spring Scheduler)是 Spring 框架中提供的定时任务框架,可以在指定的时间点或时间间隔内执行任务。Spring Task 封装了 Java 标准库中的 Timer 和ScheduledExecutorService,提供了更加简单和方便的定时任务管理方式。

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyTask {
    @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行任务
    public void execute() {
        System.out.println("定时任务执行了!当前时间:" + new Date());
    }
}

在上述代码中,我们定义了一个名为 MyTask 的类,并在其中使用 @Scheduled 注解来指定任务的执行时间和执行方式。这里使用了 cron 表达式来指定每天凌晨1点执行任务。

@Scheduled注解支持多种参数设置,例如:

  • fixedRate:表示每隔多少毫秒执行一次。
  • fixedDelay:表示延迟多少毫秒后执行。
  • initialDelay:表示启动延迟多少毫秒后执行第一次。
  • cron:使用Cron表达式来指定执行时间,例如“0 0 12 * * ?”表示每天中午12点执行。

需要注意的是,@Scheduled注解只能用于Spring容器中的Bean中,因此需要将使用该注解的类标注为@Component或其他的Spring组件注解。

cron表达式

任务执行时间cron 表达式
每分钟执行一次0 * * * * ?
每小时的第30分钟执行一次0 30 * * * ?
每天的凌晨1点执行一次0 0 1 * * ?
每周的周日凌晨1点执行一次0 0 1 ? * SUN
每月的1号凌晨1点执行一次0 0 1 1 * ?
每年的1月1日凌晨1点执行一次0 0 1 1 1 ?
每天上午10点和下午2点执行一次0 0 10,14 * * ?
每天的上午10点到11点之间每隔30秒执行一次0/30 10-11 * * * ?
每天的上午10点到11点之间每隔5分钟的1、6、11、16、21、26、31、36、41、46、51、56秒执行1,6,11,16,21,26,31,36,41,46,51,56 10-11 * * * ?

另外,如果想要快速生成 cron 表达式,可以使用在线 cron 表达式生成器,例如 cron.qqe2.com/ cron 表达式。

@EnableScheduling

使用@Scheduled需要@EnableScheduling 配合,默认 spring-boot-actuator 包会带上@EnableScheduling  注解,从而给人一种默认开启定时任务的错觉。移除对应包之后,如果用户没有在自己项目中带上 @EnableScheduling  注解,则定时任务不会生效。

Quartz

Quartz 使用 Job 和 Trigger 两个核心概念来管理任务。Job 表示要执行的任务,Trigger 表示任务的触发器,即任务执行的时间条件。Quartz 还提供了多种调度器和监听器,可以实现更加复杂的任务调度和任务管理。

以下是一个简单的 Quartz 示例:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class MyJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("定时任务执行了!当前时间:" + new Date());
    }
    public static void main(String[] args) throws SchedulerException {
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob", "group1").build();
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger", "group1")
                .startAt(DateBuilder.todayAt(1, 0, 0)).withSchedule(SimpleScheduleBuilder.repeatHourlyForever())
                .build();
        scheduler.scheduleJob(job, trigger);
        scheduler.start();
    }
}

在上述代码中,我们定义了一个名为 MyJob 的 Job 类,并在其中实现了 execute() 方法来定义具体的任务逻辑。然后,在 main() 方法中创建了一个 Scheduler 实例,并使用 JobBuilder 和 TriggerBuilder 来定义任务和触发器。这里我们使用 SimpleScheduleBuilder 来指定任务的执行间隔,即每小时执行一次。

Quartz 还支持多种触发器类型和调度器类型,例如 CronTrigger、CalendarIntervalTrigger、JobStoreTX 等,可以根据具体的需求进行选择和配置。

以上就是SpringBoot定时调度之Timer与Quartz详解的详细内容,更多关于SpringBoot定时的资料请关注脚本之家其它相关文章!

相关文章

  • 启动Tomcat时出现大量乱码的解决方法

    启动Tomcat时出现大量乱码的解决方法

    今天给大家带来的是关于Java的相关知识,文章围绕着启动Tomcat时出现大量乱码的解决方法展开,文中有非常详细的介绍及图文示例,需要的朋友可以参考下
    2021-06-06
  • JAVA获取特定格式时间方式

    JAVA获取特定格式时间方式

    我们有时要获取时间,年月日时分秒周几,有时要以特定的格式出现,本文主要介绍了JAVA获取特定格式时间方式,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • 解决java.lang.IllegalArgumentException异常问题

    解决java.lang.IllegalArgumentException异常问题

    这篇文章主要介绍了解决java.lang.IllegalArgumentException异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • java如何遍历对象中的所有属性(字段)和类型

    java如何遍历对象中的所有属性(字段)和类型

    这篇文章主要介绍了java如何遍历对象中的所有属性(字段)和类型问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java之TreeSet和TreeMap的两种排序方式解读

    Java之TreeSet和TreeMap的两种排序方式解读

    这篇文章主要介绍了Java之TreeSet和TreeMap的两种排序方式解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java中finally和return的关系实例解析

    Java中finally和return的关系实例解析

    这篇文章主要介绍了Java中finally和return的关系实例解析,总结了二者的关系,然后分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • 利用Java实现mTLS调用

    利用Java实现mTLS调用

    这篇文章主要介绍使用 Java作为客户端 与受 mTLS 保护的服务交互。为了对我们的 Java 客户端进行 ssl 配置,我们需要先设置一个 SSLContext。这简化了事情,因为 SSLContext 可用于各种 http 客户端,接下来我们一起进入下面文章了解具体内容,需要的朋友可以参考一下
    2021-11-11
  • Spring profile通过多种方法实现多环境支持

    Spring profile通过多种方法实现多环境支持

    这篇文章主要介绍了Spring profile通过多种方法实现多环境支持,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • SpringBoot如何整合redis实现过期key监听事件

    SpringBoot如何整合redis实现过期key监听事件

    这篇文章主要介绍了SpringBoot如何整合redis实现过期key监听事件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • spring boot 日志配置详解

    spring boot 日志配置详解

    本篇文章主要介绍了spring boot 日志配置 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03

最新评论