SpringBoot定时调度之Timer与Quartz详解
作者:莫念Program
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定时的资料请关注脚本之家其它相关文章!