Quartz框架使用(任務調度)


Quartz框架三大核心:

  1:scheduler

代表一個Quartz的獨立運行容器,Trigger和JobDetail可以注冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查找定位容器中某一對象的依據,Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因為它們是不同類型的)。Scheduler定義了多個接口方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。
Scheduler可以將Trigger綁定到某一JobDetail中,這樣當Trigger觸發時,對應的Job就被執行,例如:如schedulerTest.scheduleJob(jobTest, triggerTest)。一個Job可以對應多個Trigger,但一個Trigger只能對應一個Job。Scheduler擁有一個SchedulerContext,它類似於ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以訪問SchedulerContext內的信息。SchedulerContext內部通過一個Map,以鍵值對的方式維護這些上下文數據,SchedulerContext為保存和獲取數據提供了多個put()和getXxx()的方法。可以通過Scheduler# getContext()獲取對應的SchedulerContext實例。
scheduler 由 scheduler 工廠創建:包括DirectSchedulerFactory 和 StdSchedulerFactory(STD:standard標准的意思)。 第二種工廠 StdSchedulerFactory 使用較多,因為 DirectSchedulerFactory 使用起來不夠方便,需要作許多詳細的手工編碼設置。
scheduler 主要有三種:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。
scheduler 除了啟動外,scheduler 操作包括查詢、設置 scheduler 為 standby 模式、繼續、停止。
啟動scheduler 非常簡單,只需要調用 start() 方法即可。只有在scheduler 有實例或standby 模式才能調用start() 方法,一旦調用shutdown() 方法之后就不能再調用start() 方法。

2:
trigger
在 Quartz 中,trigger 是用於定義 Job 何時執行。當用 Scheduler 注冊一個 Job 的時候要創建一個 Trigger 與這個 Job 相關聯。
Quartz 中主要提供了四種類型的 Trigger:包括SimpleTrigger、CronTirgger//DateIntervalTrigger和 NthIncludedDayTrigger。這四種 trigger 可以滿足企業應用中的絕大部分需求。
最常用的是 SimpleTrigger 和 CronTrigger 。
一般來說,如果你需要在一個固定的時間和重復次數或者一個固定的間隔時間,那么 SimpleTrigger 比較合適;
如果你有許多復雜的作業調度,那么 CronTrigger 比較合適。CronTrigger 和 Unix 的 cron 機制基本一樣,基於通用的公歷,我們需要的只是熟悉cron 表達式的用法。
關於Quartz中時間表達式的設置—–corn表達式:

withIdentity() 給觸發器一些屬性 比如名字,組名。
startNow() 立刻啟動
withSchedule(ScheduleBuilder schedBuilder) 以某種觸發器觸發。
usingJobData(String dataKey, Boolean value) 給具體job傳遞參數。

3:
JobDetail & Job
jobdetail 就是對job的定義,而job是具體執行的邏輯內容。
具體的執行的邏輯需要實現 job類,並實現execute方法。
這里為什么需要有個JobDetai來作為job的定義,為什么不直接使用job?
解釋:如果使用jobdetail來定義,那么每次調度都會創建一個new job實例,這樣帶來的好處就是任務並發執行的時候,互不干擾,不會對臨界資源造成影響。
在線學習Quartz框架和API

實現簡單的demo
導入jar包
1 <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
2 <dependency>
3     <groupId>org.quartz-scheduler</groupId>
4     <artifactId>quartz</artifactId>
5     <version>1.8.6</version>
6 </dependency>
SimpleTrigger
新建任務類
 
        
 1 import org.quartz.Job;  2 import org.quartz.JobExecutionContext;  3 import org.quartz.JobExecutionException;  4  
 5 //任務類要實現job接口以及重寫execute方法
 6 public class jobDemo implements Job {  7  @Override  8     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {  9         System.out.println("這是任務類要做的任務"); 10  } 11 }
 
        

新建觸發類(這里任務調度類也寫在一起了)

 
        
 1 import org.quartz.*;  2 import org.quartz.impl.StdSchedulerFactory;  3  
 4 import java.util.Date;  5  
 6 //觸發類,觸發方法
 7 public class traggerDemo {  8     public static void main(String[] args) {  9         //要構造實例化 第一個是工作名稱 第二個是任務組 第三個是任務類
10         JobDetail jobDetail=new JobDetail("工作名稱","A",jobDemo.class); 11         //創建觸發器 第一個參數是觸發器的名稱(myTrigger) 第二個參數是執行觸發的間隔(無限觸發) 第三個參數是間隔的時長(3秒)
12         SimpleTrigger simpleTrigger=new SimpleTrigger("myTrigger",SimpleTrigger.REPEAT_INDEFINITELY,3000); 13         //創建完觸發器要設置觸發器的開始時間 現在開始
14         simpleTrigger.setStartTime(new Date()); 15  
16         //開始實例化調度類的調度工廠
17         SchedulerFactory schedulerFactory=new StdSchedulerFactory(); 18         try { 19             //獲得調度核心
20             Scheduler scheduler=schedulerFactory.getScheduler(); 21             //開始整合任務類和觸發類 第一個參數是任務類 第二個參數是觸發類
22  scheduler.scheduleJob(jobDetail,simpleTrigger); 23             //執行整合並開始任務
24  scheduler.start(); 25             //休眠15秒后關閉
26             Thread.sleep(15000); 27  scheduler.shutdown(); 28         } catch (Exception e) { 29  e.printStackTrace(); 30  } 31  
32  } 33 }
 
        

CronTrigger版

這是任務類

 
        
import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; //還是實現並重寫
public class jobDemo implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("這是表達式觸發的例子"); } }
 
        

新建觸發類(這里任務調度類也寫在一起了)

 
        
 1 import org.quartz.*;  2 import org.quartz.impl.StdSchedulerFactory;  3  
 4 import java.text.ParseException;  5 import java.util.Date;  6  
 7 public class triggerDemo {  8     public static void main(String[] args) {  9         //這是任務類,分組到B組,名字是ctg
10         JobDetail jobDetail=new JobDetail("ctg","B",jobDemo.class); 11  
12         try { 13             //設置每年每月每日的14:17:00秒觸發,這是cron表達式
14             CronTrigger cronTrigger=new CronTrigger("mytrigger2","B","0 17 14 ? * * "); 15             //立刻開啟
16             cronTrigger.setStartTime(new Date()); 17  
18             SchedulerFactory schedulerFactory=new StdSchedulerFactory(); 19             Scheduler scheduler=schedulerFactory.getScheduler(); 20  scheduler.scheduleJob(jobDetail,cronTrigger); 21  scheduler.start(); 22             Thread.sleep(30000); 23  scheduler.shutdown(); 24         } catch (ParseException e) { 25  e.printStackTrace(); 26         } catch (SchedulerException e) { 27  e.printStackTrace(); 28         } catch (InterruptedException e) { 29  e.printStackTrace(); 30  } 31  } 32 }
 
        

這是cron表達式的詳解

這是在線生成cron表達式的網址

 

spring的任務調度

整體demo結構圖

 

 
        

 還是要帶入jar包

 
        
 1 <properties>
 2         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 3         <maven.compiler.source>1.7</maven.compiler.source>
 4         <maven.compiler.target>1.7</maven.compiler.target>
 5         <!-- spring版本號 -->
 6         <spring.version>4.2.5.RELEASE</spring.version>
 7     </properties>
 8  
 9     <dependencies>
10         <dependency>
11             <groupId>junit</groupId>
12             <artifactId>junit</artifactId>
13             <version>4.11</version>
14             <scope>test</scope>
15         </dependency>
16  
17         <dependency>
18             <groupId>org.quartz-scheduler</groupId>
19             <artifactId>quartz</artifactId>
20             <version>1.8.6</version>
21         </dependency>
22  
23         <!-- 添加spring核心依賴 -->
24         <dependency>
25             <groupId>org.springframework</groupId>
26             <artifactId>spring-core</artifactId>
27             <version>${spring.version}</version>
28         </dependency>
29  
30         <dependency>
31             <groupId>org.springframework</groupId>
32             <artifactId>spring-web</artifactId>
33             <version>${spring.version}</version>
34         </dependency>
35  
36         <dependency>
37             <groupId>org.springframework</groupId>
38             <artifactId>spring-oxm</artifactId>
39             <version>${spring.version}</version>
40         </dependency>
41  
42         <dependency>
43             <groupId>org.springframework</groupId>
44             <artifactId>spring-tx</artifactId>
45             <version>${spring.version}</version>
46         </dependency>
47  
48         <dependency>
49             <groupId>org.springframework</groupId>
50             <artifactId>spring-jdbc</artifactId>
51             <version>${spring.version}</version>
52         </dependency>
53  
54         <dependency>
55             <groupId>org.springframework</groupId>
56             <artifactId>spring-webmvc</artifactId>
57             <version>${spring.version}</version>
58         </dependency>
59  
60         <dependency>
61             <groupId>org.springframework</groupId>
62             <artifactId>spring-context</artifactId>
63             <version>${spring.version}</version>
64         </dependency>
65  
66         <dependency>
67             <groupId>org.springframework</groupId>
68             <artifactId>spring-context-support</artifactId>
69             <version>${spring.version}</version>
70         </dependency>
71  
72         <dependency>
73             <groupId>org.springframework</groupId>
74             <artifactId>spring-aop</artifactId>
75             <version>${spring.version}</version>
76         </dependency>
77  
78         <dependency>
79             <groupId>org.springframework</groupId>
80             <artifactId>spring-test</artifactId>
81             <version>${spring.version}</version>
82         </dependency>
 
        

 

applicationContext.xml
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xmlns:aop="http://www.springframework.org/schema/aop"
 6        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
 7        xsi:schemaLocation="http://www.springframework.org/schema/beans
 8            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 9            http://www.springframework.org/schema/context
10            http://www.springframework.org/schema/context/spring-context-3.2.xsd
11            http://www.springframework.org/schema/aop
12            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
13            http://www.springframework.org/schema/tx
14            http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"
15        xmlns:p="http://www.springframework.org/schema/p"
16 >
17  
18     <!-- Enables the Spring Task @Scheduled programming model -->
19     <!-- 開啟定時任務 -->
20     <task:annotation-driven />
21     <!--spring掃描全部包的注解加入到Spring容器內-->
22     <context:component-scan base-package="com.bdqn.text" />
23  
24  
25 </beans>
 
        

任務觸發調度類

 
        
 1 package com.bdqn.text;  2  
 3 import org.springframework.scheduling.annotation.Scheduled;  4 import org.springframework.stereotype.Component;  5 //定義一個bean名叫ssaa方便后續調用
 6 @Component("ssaa")  7 public class SpringCronDemo1 {  8  
 9     @Scheduled(cron = " * * * ? * * ") 10     public void show(){ 11         System.out.println("這是Spring的Quartz整合測試"); 12  } 13 }
 
        

測試方法

 
        
 1 package com.bdqn.text;  2  
 3 import org.springframework.context.ApplicationContext;  4 import org.springframework.context.support.ClassPathXmlApplicationContext;  5  
 6 public class Text {  7     public static void main(String[] args) {  8         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");  9         applicationContext.getBean("ssaa",SpringCronDemo1.class).show(); 10  } 11 }
 
        

 

 
        
項目中出現的問題:
cron表達式怎么寫?
答:這個問題,有點尷尬,本來quartz框架用起來就很簡單,重點都是在於cron表達式如何寫。所以大家還是多google,這里給個地址,我當時看的一篇專欄。
https://zhuanlan.zhihu.com/p/35629505
如何禁止並發執行?
答:項目中出現了一種情況,本來job執行時間只需要10s,但是由於數據庫量增大之后,執行時間變成了60s,而我設置的間隔時間是30s,這樣就會出現上次任務還沒執行完成,下次任務就開始執行了。所以,在這種情況下,我們要禁止quart的並發操作。

2種方式:

spring中將job的concurrent屬性設置為false。默認是true 如下:
1  <bean id="scheduleJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
2         <property name="targetObject" ref="scheduleBusinessObject"/>
3         <property name="targetMethod" value="doIt"/>
4         <property name="concurrent" value="false"/>
5     </bean>

 

job類上加上注解@DisallowConcurrentExecution。
 
        
 1 @DisallowConcurrentExecution  2 public class HelloQuartz implements Job {  3 
 4  @Override  5     public void execute(JobExecutionContext jobExecutionContext) {  6         JobDetail detail = jobExecutionContext.getJobDetail();  7         String name = detail.getJobDataMap().getString("name");  8         System.out.println("my job name is  " + name + " at " + new Date());  9 
10  } 11 }
 
        

 

 
        
注意:@DisallowConcurrentExecution是對JobDetail實例生效,如果一個job類被不同的jobdetail引用,這樣是可以並發執行。
 
 
        
 1 package demos;  2 
 3 import org.quartz.DisallowConcurrentExecution;  4 import org.quartz.Job;  5 import org.quartz.JobExecutionContext;  6 import org.quartz.JobExecutionException;  7 
 8 import java.text.SimpleDateFormat;  9 import java.util.Date; 10 
11 /**
12  * @Description: 自定義任務 13  * @date 2021-11-11 23:13 14  */
15 @DisallowConcurrentExecution   // 禁止並發執行,防止間隔時間過短,上次任務還沒執行完,下次任務就開始執行了。
16 public class HelloJob implements Job { 17     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 18         //打印當前的執行時間,格式為:2017-09-06 00:00:00
19         Date date = new Date(); 20         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 21         System.out.println("當前的時間為(HelloJob):" + sf.format(date)); 22         //編寫具體的業務邏輯
23         System.out.println("Hello Job!"); 24  } 25 }
 
        

 

 
        
 1 package demos;  2 
 3 import org.quartz.*;  4 import org.quartz.impl.StdSchedulerFactory;  5 
 6 import java.text.SimpleDateFormat;  7 import java.util.Date;  8 
 9 /**
10  * @Description: 任務調度類 11  * @date 2021-11-11 23:16 12  */
13 public class HelloScheduler { 14     public static final String JOB_NAME = "myjob"; 15     public static final String JOB_GROUP = "group1"; 16     public static final String TRIGGER_NAME = "myTrigger"; 17     public static final String TRIGGER_GROUP = "group1"; 18 
19     public static void main(String[] args) throws SchedulerException { 20         /**
21  * JobDetail:用來綁定Job,並且在job執行的時候攜帶一些執行的信息 22          */
23         //創建一個JobDetail實例,將該實例與HelloJob Class綁定
24         JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity(JOB_NAME, JOB_GROUP).build(); 25         /**
26  * Trigger:用來觸發job去執行的,包括定義了什么時候去執行, 27  * 第一次執行,是否會一直重復地執行下去,執行幾次等 28          */
29         //創建一個Trigger實例,定義該job立即執行,並且每隔2秒鍾重復執行一次,直到程序停止
30         /**
31  * trigger通過builder模式來創建,TriggerBuilder.newTrigger() 32  * withIdentity():定義一個標識符,定義了組 33  * startNow():定義現在開始執行, 34  * withSchedule(SimpleScheduleBuilder.simpleSchedule():withSchedule也是builder模式創建 35  *.withIntervalInSeconds(2).repeatForever()):定義了執行頻度:每2秒鍾執行一次,不間斷地重復執行 36  * build():創建trigger 37          */
38 
39         Trigger trigger = TriggerBuilder.newTrigger() 40  .withIdentity(TRIGGER_NAME,TRIGGER_GROUP).startNow() 41  .withSchedule(SimpleScheduleBuilder.simpleSchedule() 42                         .withIntervalInSeconds(2).repeatForever()).build(); 43 
44         //創建scheduler實例:
45         /**
46  * scheduler區別於trigger和jobDetail,是通過factory模式創建的 47          */
48         //創建一個ScheduleFactory
49         SchedulerFactory sfact = new StdSchedulerFactory(); 50         Scheduler scheduler = sfact.getScheduler(); 51  scheduler.start(); 52 
53         //打印當前時間
54         Date date = new Date(); 55         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 56         System.out.println("當前的時間為(HelloScheduler):" + sf.format(date)); 57 
58         //需要將jobDetail和trigger傳進去,並將jobDetail和trigger綁定在一起。
59  scheduler.scheduleJob(jobDetail,trigger); 60  } 61 }
 
        

 

 
        
 1 package demos;  2 
 3 import org.quartz.*;  4 import org.quartz.impl.StdSchedulerFactory;  5 
 6 import java.text.SimpleDateFormat;  7 import java.util.Date;  8 
 9 /**
10  * @Description: 任務調度類 11  * @date 2021-11-11 23:16 12  */
13 public class HelloScheduler2 { 14     public static final String JOB_NAME = "myjob"; 15     public static final String JOB_GROUP = "group1"; 16     public static final String TRIGGER_NAME = "myTrigger"; 17     public static final String TRIGGER_GROUP = "group1"; 18 
19 
20     public static void main(String[] args) throws SchedulerException { 21         /**
22  * JobDetail:用來綁定Job,並且在job執行的時候攜帶一些執行的信息 23          */
24         //創建一個JobDetail實例,將該實例與HelloJob Class綁定
25         JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity(JOB_NAME, JOB_GROUP).build(); 26         /**
27  * Trigger:用來觸發job去執行的,包括定義了什么時候去執行, 28  * 第一次執行,是否會一直重復地執行下去,執行幾次等 29          */
30 
31         // 創建cron表達式
32         Trigger trigger = TriggerBuilder.newTrigger() 33  .withIdentity(TRIGGER_NAME,TRIGGER_GROUP).startNow() 34                 .withSchedule(CronScheduleBuilder.cronSchedule("0 0/1 8-20 * * ?")).build(); // // 每天8:00-20:00,每隔1分鍾執行一次 35 
36         //創建scheduler實例:
37         /**
38  * scheduler區別於trigger和jobDetail,是通過factory模式創建的 39          */
40         //創建一個ScheduleFactory
41         SchedulerFactory sfact = new StdSchedulerFactory(); 42         Scheduler scheduler = sfact.getScheduler(); 43  scheduler.start(); 44 
45         //打印當前時間
46         Date date = new Date(); 47         SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 48         System.out.println("當前的時間為(HelloScheduler):" + sf.format(date)); 49 
50         //需要將jobDetail和trigger傳進去,並將jobDetail和trigger綁定在一起。
51  scheduler.scheduleJob(jobDetail,trigger); 52  } 53 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM