Quartz學習總結

1、quartz介紹

Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,是徹底由java開發的一個開源的任務日程管理系統,「任務進度管理器」就是一個在預先肯定(被歸入日程)的時間到達時,負責執行(或者通知)其餘軟件組件的系統。java

Quartz用一個小Java庫發佈文件(.jar文件),這個庫文件包含了全部Quartz核心功能。這些功能的主要接口(API)是Scheduler接口。它提供了簡單的操做,例如:將任務歸入日程或者從日程中取消,開始/中止/暫停日程進度。mysql

2、核心概念

Quartz 任務調度的核心元素是 scheduler, trigger 和 job,其中 trigger 和 job 是任務調度的元數據, scheduler 是實際執行調度的控制器。spring

一、trigger

觸發器,用於定於任務調度的時間規則,即按照什麼時間規則去執行任務。Quartz 中主要提供了四種類型的 trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和 NthIncludedDayTrigger。Trigger也有一個相關聯的JobDataMap,用於給Job傳遞一些觸發相關的參數。
最經常使用的:
SimpleTrigger:用來觸發只需執行一次或者在給定時間觸發而且重複N次且每次執行延遲必定時間的任務。
CronTrigger:按照日曆觸發,例如「每一個週五」,每月10日中午或者10:15分。sql

二、job

被調度的任務,主要有兩種類型的 job:無狀態的(stateless)和有狀態的(stateful)。數據庫

  1. Quartz無狀態Job實現了org.quartz.Job接口,有狀態Job實現了org.quartz.StatefulJob接口。
  2. 對於同一個 trigger 來講,有狀態的 job 不能被並行執行,只有上一次觸發的任務被執行完以後,才能觸發下一次執行。
  3. 一個 job 能夠被多個 trigger 關聯,可是一個 trigger 只能關聯一個 job。

三、scheduler

任務調度器,由 scheduler 工廠建立:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二種工廠 StdSchedulerFactory 使用較多,由於 DirectSchedulerFactory 使用起來不夠方便,須要做許多詳細的手工編碼設置。 Scheduler 主要有三種:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。服務器

四、做業管理和存儲

做業一旦被調度,調度器須要記住而且跟蹤做業和它們的執行次數。Quartz經過一個稱之爲做業存儲(JobStore)的概念來作做業存儲和管理。併發

Quartz提供兩種基本做業存儲類型。第一種類型叫作RAMJobStore,它利用內存來持久化調度程序信息。
優勢: 不要外部數據庫,配置容易,運行速度快
缺點: 由於調度程序信息是存儲在被分配給JVM的內存裏面,因此,當應用程序中止運行時,全部調度信息將被丟失。另外由於存儲到JVM內存裏面,因此能夠存儲多少個Job和Trigger將會受到限制less

第二種類型的做業存儲稱爲JDBC做業存儲,提供兩種不一樣的實現。兩種JDBC做業存儲都須要JDBC驅動程序和後臺數據庫來持久化調度程序信息。這兩種類型的不一樣在於你是否想要控制數據庫事務或者釋放控制給應用服務器(這相似於J2EE領域中,容器管理事務CMT和Bean管理事務BMT之間的區別),這兩種JDBC做業存儲是:
JobStoreTX:當你想要控制事務或工做在非應用服務器環境中時使用;
JobStoreCMT:當你工做在應用服務器環境中和想要容器控制事務時使用。
優勢: 支持集羣,由於全部的任務信息都會保存到數據庫中,能夠控制事物,還有就是若是應用服務器關閉或者重啓,任務信息都不會丟失,而且能夠恢復因服務器關閉或者重啓而致使執行失敗的任務
缺點: 運行速度的快慢取決與鏈接數據庫的快慢ide

3、核心類和關係

1.核心類

  • QuartzSchedulerThread :負責執行向QuartzScheduler註冊的觸發Trigger的工做的線程。
  • ThreadPool:Scheduler使用一個線程池做爲任務運行的基礎設施,任務經過共享線程池中的線程提供運行效率。
  • QuartzSchedulerResources:包含建立QuartzScheduler實例所需的全部資源(JobStore,ThreadPool等)。
  • SchedulerFactory :提供用於獲取調度程序實例的客戶端可用句柄的機制。
  • JobStore: 經過類實現的接口,這些類要爲org.quartz.core.QuartzScheduler的使用提供一個org.quartz.Job和org.quartz.Trigger存儲機制。做業和觸發器的存儲應該以其名稱和組的組合爲惟一性。
  • QuartzScheduler :這是Quartz的核心,它是org.quartz.Scheduler接口的間接實現,包含調度org.quartz.Jobs,註冊org.quartz.JobListener實例等的方法。
  • Scheduler :這是Quartz Scheduler的主要接口,表明一個獨立運行容器。調度程序維護JobDetails和觸發器的註冊表。 一旦註冊,調度程序負責執行做業,當他們的相關聯的觸發器觸發(當他們的預約時間到達時)。
  • Trigger :具備全部觸發器通用屬性的基本接口,描述了job執行的時間出發規則。 - 使用TriggerBuilder實例化實際觸發器。
  • JobDetail :傳遞給定做業實例的詳細信息屬性。 JobDetails將使用JobBuilder建立/定義。
  • Job:要由表示要執行的「做業」的類實現的接口。只有一個方法 void execute(jobExecutionContext context)
    (jobExecutionContext 提供調度上下文各類信息,運行時數據保存在jobDataMap中)
    Job有個子接口StatefulJob ,表明有狀態任務。
    有狀態任務不可併發,前次任務沒有執行完,後面任務處於阻塞等到。

2.關係:

4、quartz使用

1.依賴

<dependency>

    <groupId>org.quartz-scheduler</groupId>

    <artifactId>quartz</artifactId>
    
<version>2.2.3</version>
 
</dependency>
<dependency>

    <groupId>org.quartz-scheduler</groupId>

    <artifactId>quartz-jobs</artifactId>

    <version>2.2.3</version>
 
</dependency>

2.原生應用

定義jobui

public class MyJob implements Job {
    private static Logger logger = LoggerFactory.getLogger(MyJob.class);
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //打印當前的執行時間 例如 2019-11-12 00:00:00
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("如今的時間是:"+ sf.format(date));
        //具體的業務邏輯
        System.out.println("開始生成任務報表 或 開始發送郵件");
        logger.info("開始執行定時任務");
    }
}

建立trigger,schedule,並啓動定時任務

//建立一個jobDetail的實例,將該實例與HelloJob Class綁定
JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("myJob").build();
//建立一個Trigger觸發器的實例,定義該job當即執行,而且每2秒執行一次,一直執行
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity("myTrigger").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();
//建立schedule實例
StdSchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
scheduler.scheduleJob(jobDetail,trigger);

3.Quartz+Spring集成使用

先使用quartz自帶的建表語句建立表.
配置quartz.properties,以下:

# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
# 調度器實例的名字,使用默認的DefaultQuartzScheduler就好
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
# 調度器實例的ID, 選擇AUTO
org.quartz.scheduler.instanceId:AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
# 跳過更新檢查
org.quartz.scheduler.skipUpdateCheck:true
# 配置線程池
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#
# quartz默認的是將job信息存儲在內存中,quartz集羣必須將job信息持久化到數據庫中
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.misfireThreshold:60000
############
org.quartz.jobStore.useProperties:true
#quartz數據表的前綴,quartz的數據表在 quartz-2.2.3\docs\dbTables 文件夾中,
#選擇對應的數據庫版本,將數據庫建立出來
org.quartz.jobStore.tablePrefix:QRTZ_
# 最關鍵的  是否支持集羣 選擇true
org.quartz.jobStore.isClustered:true
org.quartz.jobStore.clusterCheckinInterval:15000
# dataSource
#org.quartz.jobStore.dataSource:myDS
#org.quartz.dataSource.myDS.connectionProvider.class:com.abc.util.MyPoolingconnectionProvider
#org.quartz.dataSource.myDS.driver: com.mysql.jdbc.Driver 
#org.quartz.dataSource.myDS.url: jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8 
#org.quartz.dataSource.myDS.user: root 
#org.quartz.dataSource.myDS.password: root 
#org.quartz.dataSource.myDS.maxConnections: 10

db.properties:

#quartz配置對應數據庫
jdbc.quartz.driver=com.mysql.jdbc.Driver
jdbc.quartz.url=jdbc:mysql://127.0.0.1:26500/quartz?useUnicode=true&characterEncoding=utf-8
jdbc.quartz.username=root
jdbc.quartz.password=vislecaina

spring-quartz.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                        ">

    <!-- 任務 -->
    <bean id="jobDetailFactoryBeanExample" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.fiberhome.quartz.task.job.MyJob"/>
        <!-- 執行完成仍保留在數據庫中 -->
        <property name="durability" value="true"/>
        <!-- 這裏設置的jobDataAsMap能夠傳遞一些參數給做業任務 -->
        <property name="jobDataAsMap">
            <map>
                <entry key="wish" value="hello"/>
            </map>
        </property>
    </bean>

    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <!-- 這裏的JobDetail指的就是咱們配置的做業任務的bean -->
        <property name="jobDetail" ref="jobDetailFactoryBeanExample" />
        <!-- 延遲5秒開始 -->
        <property name="startDelay" value="5000"></property>
        <!-- 每3秒重複一次 -->
        <property name="repeatInterval" value="60000"></property>
    </bean>

    <bean id="startQuartz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
        <property name="configLocation" value="classpath:quartz.properties" />
        <property name="dataSource" ref="quartzDataSource" />
        <!-- 若是這個覆蓋配置爲false,quratz啓動之後將以數據庫的數據爲準,配置文件的修改不起做用。-->
        <property name="overwriteExistingJobs" value="true" />
        <!--指定使用哪些觸發器,spring會去調度觸發相應的觸發器,進而對做業任務進行調度處理-->
        <property name="triggers">
            <list>
                <ref bean="simpleTrigger"/>
            </list>
        </property>
        <property name="jobFactory">
            <bean class="com.fiberhome.quartz.task.jobfactory.JobFactory"/>
        </property>
        <property name="startupDelay" value="1"/>
    </bean>

</beans>

Job類:

public class MyJob implements Job {

    @Autowired
    private UserService userService;
    /**
     * 要實現的任務
     *
     * @param context job上下文
     * @throws JobExecutionException
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        User user = userService.getUser(1001);
        System.out.println("執行定時任務...");
        System.out.println(user);
    }
}

JobFactory類:

public class JobFactory extends SpringBeanJobFactory {

    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object jobInstance = super.createJobInstance(bundle);
        autowireCapableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}
相關文章
相關標籤/搜索