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定时的资料请关注脚本之家其它相关文章!

相关文章

  • Java实现学生信息管理系统IO版本

    Java实现学生信息管理系统IO版本

    这篇文章主要为大家详细介绍了Java实现学生信息管理系统IO版本,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • SpringSecurity Demo 创建项目的过程详解

    SpringSecurity Demo 创建项目的过程详解

    本文介绍了使用SpringBoot 3.2.4创建一个简单的安全验证项目的过程,包括引入依赖、配置文件修改、创建控制器和启动类等步骤,并最终成功启动项目并在浏览器访问到请求接口,感兴趣的朋友跟随小编一起看看吧
    2026-04-04
  • Java中的数组基础知识学习教程

    Java中的数组基础知识学习教程

    这篇文章主要介绍了Java中的数组基础知识学习教程,文中同时也整理了Java对数字类型的支持状况及Number类中的方法,需要的朋友可以参考下
    2016-02-02
  • pdf2swf+flexpapers实现类似百度文库pdf在线阅读

    pdf2swf+flexpapers实现类似百度文库pdf在线阅读

    这篇文章主要介绍了pdf2swf+flexpapers实现类似百度文库pdf在线阅读的相关资料,需要的朋友可以参考下
    2014-10-10
  • Java中double和float类型的区别与使用方法

    Java中double和float类型的区别与使用方法

    float和double都是用来表示浮点数的数据类型,但是它们之间有一些区别,这篇文章主要给大家介绍了关于Java中double和float类型的区别与使用方法的相关资料,需要的朋友可以参考下
    2024-07-07
  • 基于Java实现回调监听工具类

    基于Java实现回调监听工具类

    这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • SpringBoot整合数据库连接池Druid的错误详解

    SpringBoot整合数据库连接池Druid的错误详解

    文章总结了几种SpringBoot整合Druid时遇到的问题及其解决方法,主要问题有:缺少jar包导致系统停止和ClassNotFoundException,通过添加缺少的jar包可以解决问题,同时提醒注意数据库配置信息的正确性和避免jar包冲突
    2026-04-04
  • SpringBoot之Banner的使用示例

    SpringBoot之Banner的使用示例

    本篇文章主要介绍了SpringBoot之Banner的使用示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • 最最常用的 100 个 Java类分享

    最最常用的 100 个 Java类分享

    这篇文章主要介绍了最最常用的 100 个 Java类分享,需要的朋友可以参考下
    2015-04-04
  • Java版本兼容性之JDK 21的SDK在JDK 1.8的使用解读

    Java版本兼容性之JDK 21的SDK在JDK 1.8的使用解读

    文章介绍了Java的字节码版本机制以及如何处理UnsupportedClassVersionError错误,文章首先解释了JVM如何通过检查.class文件的字节码版本号来确定是否可以运行该文件,然后给出了三个解决方案:统一环境、交叉编译和多版本JAR
    2025-11-11

最新评论