quartz定时任务

简介: quartz定时任务

介绍

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。
Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。

quartz 核心部分

  • job 执行器,用户实现业务逻辑
  • jobdetail 任务,关联具体的job
  • trigger 触发器, 什么时候执行
  • Scheduler 调度器

常用的Trigger有SimpleTrigger和CronTrigger

Job jobDetail

JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

为什么设计成JobDetail + Job,不直接使用Job

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。
这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

JobExecutionContext
JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息。
当Schedule调度执行一个Job的时候,就会将JobExecutionContext传递给该Job的execute()中,Job就可以通过JobExecutionContext对象获取信息。

Trigger

SimpleTrigger 可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。

CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式.

可通过在线生成Cron表达式的工具:http://cron.qqe2.com/ 来生成自己想要的表达式。

代码说明

依赖jar

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>

调度器Scheduler的使用

public class QuartzTest {
      public static void main(String[] args) {
          try {
              // 从factory创建调度器 Scheduler
              Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

              // 启动
              scheduler.start();
                            ...
              // 关闭
              scheduler.shutdown();
          } catch (SchedulerException se) {
              se.printStackTrace();
          }
      }
  }

JobDetail、Trigger的使用

HelloJob 为实现job接口的类,处理用户业务逻辑的job

// define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("job1", "group1")
      .build();

  // Trigger the job to run now, and then repeat every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("trigger1", "group1")
      .startNow()
            .withSchedule(simpleSchedule()
              // 间隔40s
              .withIntervalInSeconds(40)
              .repeatForever())            
      .build();

  // Tell quartz to schedule the job using our trigger
  scheduler.scheduleJob(job, trigger);

一个完整的例子

package org.quartz.examples.example1;

import static org.quartz.DateBuilder.evenMinuteDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * This Example will demonstrate how to start and shutdown the Quartz scheduler and how to schedule a job to run in
 * Quartz.
 * 
 * @author Bill Kratzer
 */
public class SimpleExample {

  public void run() throws Exception {
    Logger log = LoggerFactory.getLogger(SimpleExample.class);

    log.info("------- Initializing ----------------------");

    // First we must get a reference to a scheduler
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = sf.getScheduler();

    log.info("------- Initialization Complete -----------");

    // computer a time that is on the next round minute
    Date runTime = evenMinuteDate(new Date());

    log.info("------- Scheduling Job  -------------------");

    // define the job and tie it to our HelloJob class
    JobDetail job = newJob(HelloJob.class).withIdentity("job1", "group1").build();

    // Trigger the job to run on the next round minute
    Trigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(runTime).build();

    // Tell quartz to schedule the job using our trigger
    sched.scheduleJob(job, trigger);
    log.info(job.getKey() + " will run at: " + runTime);

    // Start up the scheduler (nothing can actually run until the
    // scheduler has been started)
    sched.start();

    log.info("------- Started Scheduler -----------------");

    // wait long enough so that the scheduler as an opportunity to
    // run the job!
    log.info("------- Waiting 65 seconds... -------------");
    try {
      // wait 65 seconds to show job
      Thread.sleep(65L * 1000L);
      // executing...
    } catch (Exception e) {
      //
    }

    // shut down the scheduler
    log.info("------- Shutting Down ---------------------");
    sched.shutdown(true);
    log.info("------- Shutdown Complete -----------------");
  }

  public static void main(String[] args) throws Exception {

    SimpleExample example = new SimpleExample();
    example.run();

  }

}
    
public class HelloJob implements Job {

    private static Logger _log = LoggerFactory.getLogger(HelloJob.class);

    /**
     * <p>
     * Empty constructor for job initilization
     * </p>
     * <p>
     * Quartz requires a public empty constructor so that the
     * scheduler can instantiate the class whenever it needs.
     * </p>
     */
    public HelloJob() {
    }

    /**
     * <p>
     * Called by the <code>{@link org.quartz.Scheduler}</code> when a
     * <code>{@link org.quartz.Trigger}</code> fires that is associated with
     * the <code>Job</code>.
     * </p>
     * 
     * @throws JobExecutionException
     *             if there is an exception while executing the job.
     */
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        // Say Hello to the World and display the date/time
        _log.info("Hello World! - " + new Date());
    }

}

总结

Quartz包含4部分job、jobdetail、trigger、Scheduler。通过StdSchedulerFactory工厂创建调度器Scheduler,调度器关联trigger与jobDetail,trigger触发任务通知scheduler查找jobDetail 创建job实例执行用户定义的业务任务。

相关文章
|
Linux
LINUX CUPS下载源码并编译
LINUX CUPS下载源码并编译
744 0
|
3月前
|
安全 芯片 Windows
U盘插上后显示为空?其实数据没丢,可以这样恢复
U盘变空并不等于数据丢失!本文详解U盘插入提示“格式化”、显示为空等常见问题的原因,教你如何在不格式化的前提下恢复数据,修复异常,并避免再次发生。内容涵盖逻辑错误识别、恢复软件使用步骤及U盘是否还能继续使用的判断方法,助你轻松应对U盘故障。
|
缓存 中间件
Nest.js 实战 (九):使用拦截器记录用户 CURD 操作日志
这篇文章介绍了在Nest.js中如何实现记录用户CURD操作的需求。首先解释了什么是拦截器以及拦截器的作用,然后通过创建Prisma模型,添加Log模型,并通过编写LoggerInterceptor拦截器,实现了记录用户操作的功能。最后通过效果演示和总结,强调了使用拦截器实现此功能的有效性。
246 0
Nest.js 实战 (九):使用拦截器记录用户 CURD 操作日志
|
Java 数据库连接 mybatis
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
在进行springboot和mybatis遇到了这个错误 Servlet.service() for servlet [dispatcherServlet] in context with path [] th
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
|
机器学习/深度学习 供应链 监控
ERP系统中的供应链风险识别与应对策略解析
【7月更文挑战第25天】 ERP系统中的供应链风险识别与应对策略解析
931 1
|
Kubernetes 网络协议 安全
Spring Cloud Alibaba 应用如何平滑迁移至 IPv6?
一次性迁移不仅在基础设施层面不可行,对企业用户来说,就算基础设施都能准备完毕,让其将少则上百,多则成千上万的应用实例在一段时间内一次性停机进行协议栈迁移,无论是在风险上,还是成本上,对企业用户来说都是难以接受的!
394 64
Spring Cloud Alibaba 应用如何平滑迁移至 IPv6?
|
JavaScript Java API
云效问题之流水线使用npm制品仓库构建拉取依赖特别慢如何解决
云效仓库是阿里云提供的代码托管和版本控制服务,支持Git等多种版本管理工具;本合集聚焦于云效仓库的使用技巧、团队协作流程以及常见问题解答,旨在帮助开发者更高效地进行代码管理和协作开发。
487 0
|
Linux
嵌入式 Linux下修改MAC地址
Linux下修改MAC地址 方法一: 1.关闭网卡设备ifconfig eth0 down2.修改MAC地址ifconfig eth0 hw ether MAC地址3.重启网卡ifconfig eth0 up 方法二:以上方法一修改后linux重启后MAC又恢复为原来的,为了下次启动时修改后的MAC仍有效,我们可以修改文件file:/etc/rc.
3563 0
|
SQL 存储 分布式计算
VectorizedReader 和 ORC
spark SQL not only SQL 1.SparkSession/DataFrame/Datasets API 2.
3586 0
|
iOS开发 Docker MacOS
【已解决】Docker Desktop “Fatal Error: exit status 1“
【已解决】Docker Desktop “Fatal Error: exit status 1“
830 0