Quartz定时器与定时任务知识概括

本文详细介绍了Quartz定时任务调度,包括定时任务的概念、使用场景和常见实现技术。对比了Timer、ScheduledExecutorService、Spring Task和Quartz,重点讨论了Quartz的特性、配置、集群与分布式实现。Quartz作为强大的定时框架,支持多线程、集群和丰富的调度策略,适合复杂任务需求。文章还探讨了Spring与Quartz的集成,并提供了相关配置示例。

定时任务调度

什么是定时任务:

  • 定时任务是指调度程序在指定的时间或周期触发执行的任务
  • 使用场景:发送邮件、统计、状态修改、消息推送、活动开启、增量索引

定时任务实现技术:

  • Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。使用较少。
  • ScheduledExecutorService:也是jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
  • Spring3.0以后自主开发的定时任务工具spring task,使用简单,支持线程池,可以高效处理许多不同的定时任务,除spring相关的包外不需要额外的包,支持注解和配置文件两种形式。不能处理过于复杂的任务
  • 专业的定时框架quartz,功能强大,可以让你的程序在指定时间执行,也可以按照某一个频度执行,支持数据库、监听器、插件、集群。一般使用spring整合quartz或者springboot整合quartz。

其他定时器

Timer:

/**
 * java timer 测试类
 * Created by gaozhy on 2017/6/24.
 */
public class JavaTimer {
   
   

    public static void main(String[] args) {
   
   
        try {
   
   
            // 创建定时器
            Timer timer = new Timer();

            // 添加调度任务
            // 安排指定的任务在指定的时间开始进行重复的 固定延迟执行
            timer.schedule(new MyTask(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-06-24 22:31:10"),10*1000);
            // 安排指定的任务在指定的延迟后开始进行重复的 固定速率执行
            //timer.scheduleAtFixedRate(new MyTask(),new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-06-24 22:31:10"),10*1000);
        } catch (ParseException e) {
   
   
            e.printStackTrace();
        }
    }
}
/**
 * 任务类
 * Created by gaozhy on 2017/6/24.
 */
public class MyTask extends TimerTask{
   
   

    // 定义调度任务
    public void run() {
   
   
        System.out.println("log2:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

ScheduledExecutorService:

  • 该方法跟Timer类似,直接看demo:
public class TestScheduledExecutorService {
   
   

   public static void main(String[] args) {
   
   

       ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

       // 参数:1、任务体 2、首次执行的延时时间
       //      3、任务执行间隔 4、间隔时间单位
       service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);

   }

}

Spring Task:

  • 基于配置:
/**
 * Spring Task 任务类
 * Created by gaozhy on 2017/6/24.
 */

public class SpringTask {
   
   

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public void m1(){
   
   
        System.out.println("m1:"+simpleDateFormat.format(new Date()));
    }

    public void m2(){
   
   
        System.out.println("m2:"+simpleDateFormat.format(new Date()));
    }

    public void m3(){
   
   
        System.out.println("m2:"+simpleDateFormat.format(new Date()));
    }
}
<!--spring-task.xml配置-->
<bean id="springTask" class="com.baizhi.task.SpringTask"></bean>
   <!--注册调度任务-->
   <task:scheduled-tasks>
       <!--延迟8秒 执行任务-->
       <!--<task:scheduled ref="springTask" method="m1" fixed-delay="8000" />-->

       <!--固定速度5秒 执行任务-->
       <!--<task:scheduled ref="springTask" method="m2" fixed-rate="5000"/>-->

       <!--
           使用cron表达式 指定触发时间
           spring task 只支持6位的cron表达式 秒 分 时 日 月 星期
       -->
       <task:scheduled ref="springTask" method="m3" cron="50-59 * * ? * *"/>
   </task:scheduled-tasks>

   <!--执行器配置-->
   <task:executor id="threadPoolTaskExecutor" pool-size="10" keep-alive="5"></task:executor>

   <!--调度器配置-->
   <task:scheduler id="threadPoolTaskScheduler" pool-size="10"></task:scheduler>
  • 基于注解
/**
 * Spring Task 任务类
 * Created by gaozhy on 2017/6/24.
 */
public class SpringAnnotationTask {
   
   

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

   /* @Scheduled(fixedDelay = 8000)
    public void m1(){
        System.out.println("m1:"+simpleDateFormat.format(new Date()));
    }

    @Scheduled(fixedRateString = "5000")
    public void m2(){
        System.out.println("m2:"+simpleDateFormat.format(new Date()));
    }
    */
    @Scheduled(cron = "0-30 * * * * ?")
    public void m3(){
   
   
        System.out.println("m2:"+simpleDateFormat.format(new Date()));
    }
}
<!--开启基于注解的spring task-->
<task:annotation-driven></task:annotation-driven>

<bean id="springAnnotationTask" class="com.baizhi.task.SpringAnnotationTask"></bean>

Spring Task任务执行和调度(TaskExecutor,TaskSchedule):

  • 介绍:
    Spring Framework分别使用TaskExecutor和TaskScheduler接口提供异步执行和任务调度的抽象。Spring还具有支持线程池或在应用程序服务器环境中委托给CommonJ的接口的实现。最终,在公共接口背后使用这些实现抽象出了JavaSE 5,Java SE 6和Java EE环境之间的差异。
    ②Spring还提供了集成类,用于支持使用Timer(自1.3以来的JDK的一部分)和Quartz Scheduler(http://quartz-scheduler.org)进行调度。这两个调度程序都是使用FactoryBean设置的,它们分别具有对Timer或Trigger实例的可选引用。此外,还提供了Quartz Scheduler和Timer的便捷类,它允许您调用现有目标对象的方法(类似于正常的MethodInvokingFactoryBean操作)。
  • Spring官方对TaskExecutor的相关解释:
    Spring的TaskExecutor接口与java.util.concurrent.Executor接口相同。该接口具有单个方法(execute(Runnable task)),该方法根据线程池的语义和配置接受要执行的任务。
    ②TaskExecutor接口相关实现类:
实现类名 对应解释(直接甩翻译了)
SyncTaskExecutor 该实现类不会执行异步调用。 相反,每次调用都在调用的线程中进行(翻译过来也即同步任务执行器)。 它主要用于不需要多线程的情况,例如在简单的测试用例中。
SimpleAsyncTaskExecutor 此实现不会重用任何线程。 相反,它为每次调用启动一个新线程。 但是,它确实支持并发限制,该限制会阻止超出限制的任何调用,直到释放插槽为止。(说简单了,就是要使用了直接创建一个线程)
ConcurrentTaskExecutor 此实现是java.util.concurrent.Executor实例的适配器。很少需要直接使用ConcurrentTaskExecutor**(官网自己都觉得很少使用,不过相对于ThreadPoolTaskExecutor,官网推荐如果ThreadPoolTaskExecutor不够灵活,无法满足需求,则可以使用ConcurrentTaskExecutor)**。
ThreadPoolTaskExecutor 杀手锏级的任务调度器(最常用),可以说已经足够满足我们的需求了(除非,非常非常特例才使用ConcurrentTaskExecutor)。官网翻译重要片段:公开了bean属性,用于配置java.util.concurrent.ThreadP
WorkManagerTaskExecutor 此实现使用CommonJ WorkManager作为其后备服务提供程序,并且是在Spring应用程序上下文中在WebLogic或WebSphere上设置基于CommonJ的线程池集成的中心便利类。
DefaultManagedTaskExecutor 此实现在JSR-236兼容的运行时环境(例如Java EE 7+应用程序服务器)中使用JNDI获取的ManagedExecutorService,为此目的替换CommonJ WorkManager。(说明了就是依赖环境)
  • Spring官方对TaskSheduler接口的相关解释:
    用于在将来的某个时间点调度任务。
    ②TaskScheduler接口相关实现类:
实现类名 对应解释
ConcurrentTaskScheduler 该类实际继承了ConcurrentTaskExecutor对象。只是实现了TaskScheduler接口,增加了相关定时调度任务的方法。
ThreadPoolTaskScheduler spring对该类设计原则同ThreadPoolTaskExecutor类。是为了定时调度任务不依赖相关的运行容器(例如weblogic、WebSphere等)。其底层委托给ScheduledExecutorService,向外暴露相关的常见bean配置属性。
  • 总结:
    ①链接:
    <1>spring任务执行器与任务调度器
    <2>JAVA定时任务Timer、Spring Task、Quartz
    Quartz与Spring Task对比:
    <1>Quartz:
    1、默认多线程异步执行
    2、单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。业务繁忙时,一个任务会有多个调度,可能导致数据处理异常。
    3、多个任务时,任务之间没有直接影响,多任务执行的快慢取决于CPU的性能
    4、触发方式 : (1)SimpleTrigger (2)CronTrigger
    5、能被集群实例化,支持分布式部署
    6、使用JobStoreCMT(JDBCJobStore的子类),Quartz 能参与JTA事务;Quartz 能管理JTA事务(开始和提交)在执行任务之间,这样,任务做的事就可以发生在JTA事务里。
    <2>Task:
    1、默认单线程同步执行
    2、单个任务时,当前次的调度完成后,再执行下一次任务调度
    3、多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程
    4、触发方式:与Quartz的CronTrigger的表达式类似,可以使用注解标注定时任务。

Quartz简介

Quartz简介:

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

springboot定时任务(与Quartz整合):

  • 直接加入集成好的starter
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

定时器种类:

  • Quartz 中五种类型的Trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,NthIncludedDayTrigger和Calendar类( org.quartz.Calendar)。
  • 最常用的:
    ①SimpleTrigger:用来触发只需执行一次或者在给定时间触发并且重复N次且每次执行延迟一定时间的任务。
    ②CronTrigger:按照日历触发,例如“每个周五”,每个月10日中午或者10:15分。

存储方式:

  • RAMJobStore和JDBCJobStore对比:
类型 优点 缺点
RAMJobStore 不要外部数据库,配置容易,运行速度快 因为调度程序信息是存储在被分配给JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到JVM内存里面,所以可以存储多少个Job和Trigger将会受到限制
JDBCJobStore 支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务 运行速度的快慢取决与连接数据库的快慢

表关系和解释:

  • 表关系:
    在这里插入图片描述
  • 解释:
表名称 说明
qrtz_blob_triggers Trigger作为Blob类型存储(用于Quartz用户用JDBC创建他们自己定制的Trigger类型,JobStore 并不知道如何存储实例的时候)
qrtz_calendars 以Blob类型存储Quartz的Calendar日历信息, quartz可配置一个日历来指定一个时间范围
qrtz_cron_triggers 存储Cron Trigger,包括Cron表达式和时区信息。
qrtz_fired_triggers 存储与已触发的Trigger相关的状态信息,以及相联Job的执行信息
qrtz_job_details 存储每一个已配置的Job的详细信息
qrtz_locks 存储程序的非观锁的信息(假如使用了悲观锁)
qrtz_paused_trigger_graps 存储已暂停的Trigger组的信息
qrtz_scheduler_state 存储少量的有关 Scheduler的状态信息,和别的 Scheduler 实例(假如是用于一个集群中)
qrtz_simple_triggers 存储简单的 Trigger,包括重复次数,间隔,以及已触的次数
qrtz_triggers 存储已配置的 Trigger的信息

核心类和关系:

  • 核心类:
    QuartzSchedulerThread:负责执行向QuartzScheduler注册的触发Trigger的工作的线程。
    ThreadPool:Scheduler使用一个线程池作为任务运行的基础设施,任务通过共享线程池中的线程提供运
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值