Quartz是什麼
Quartz是一個功能強大的開源任務排程庫,幾乎可以整合到任何Java應用程式中,無論是超小型的獨立應用還是超大型電子商務系統。
它常用於企業級應用中:
Driving Process Workflow:當新訂單下達,可以安排一個30分鐘內觸發的任務,檢查訂單狀態。System Maintenance:安排每個工作日晚上11點將資料庫內容轉儲到檔案的任務。Providing reminder services:提供提醒服務。Quartz還支援叢集模式和對JTA服務。
Quartz中的重要API及概念http://www.quartz-scheduler.org/documentation/quartz-2.2.2/tutorials/
超重要APIScheduler 和排程程式互動的主要API生命週期從SchedulerFactoru建立它開始,到呼叫shutdown方法結束。一旦Scheduler建立,任何關於scheduling相關的事,他都為所欲為:新增、刪除、列出所有的Jobs和triggers、暫停觸發器等。在start方法之前,不會做任何事情。Job 你希望被排程器排程的任務元件介面。當Job的觸發器觸發時,排程程式的工作執行緒將呼叫execute方法。該方法接收一個JobExecutionContext物件,為Job例項提供了豐富的執行時環境資訊,比如:scheduler、trigger、jobDataMap、job、calendar、各種time等。JobDetail 用於定義任務。JobDetail物件由Quartz客戶端在將job加入Scheduler提供,也就是你的程式。它包含了不同為job設定的屬性,還有可以用來為job儲存狀態資訊的JobDataMap。注意它和Job的區別,它實際上是Job例項的屬性。【Job定義如何執行,JobDetail定義有何屬性】Trigger 觸發任務執行。觸發器可能具有與之關聯的JobDataMap,以便於將特定於觸發器觸發的引數傳遞給Job。Quartz提供了幾種不同的觸發器,SimpleTrigger和CronTrigger比較常用。如果你需要一次性執行作業或需要在給定的時間觸發一個作業並重復執行N次且有兩次執行間有延時delay,SimpleTrigger較為方便。如果你希望基於類似日期表觸發執行任務,CronTrgger推薦使用。JobBuilder 用於構建JobDetail的。TriggerBuilder 用於構建Trigger的。Quartz提供了各種各樣的Builder類,定義了Domain Specific Language,且都提供了靜態的建立方法,我們可以使用import static簡化書寫。
重要概念Identity當作業和觸發器在Quartz排程程式中註冊時,會獲得標識鍵。JobKey和TriggerKey允許被置入group中,易於組織管理。唯一的,是name和group的組合標識。JobDataMap是Map的實現,具有key-value相關操作,儲存可序列化資料物件,供Job例項在執行時使用。可以使用usingJobData(key,value)在構建Jobdetail的時候傳入資料,使用jobDetail.getJobDataMap()獲取map。Quartz設計理念:為什麼設計Job和Trigger?While developing Quartz, we decided that it made sense to create a separation between the schedule and the work to be performed on that schedule. This has (in our opinion) many benefits. For example, Jobs can be created and stored in the job scheduler independent of a trigger, and many triggers can be associated with the same job. Another benefit of this loose-coupling is the ability to configure jobs that remain in the scheduler after their associated triggers have expired, so that that it can be rescheduled later, without having to re-define it. It also allows you to modify or replace a trigger without having to re-define its associated job.
隔離schedule和schedule上執行的Job,優點是可見的:
可以獨立於觸發器建立作業並將其儲存在作業排程程式中,並且許多觸發器可以與同一作業相關聯。這樣的松耦合好處是什麼?
如果觸發器過期,作業還可以保留在程式中,以便重新排程,而不必重新定義。如果你希望修改替換某個觸發器,你不必重新定義其關聯的作業。最簡單的Quartz使用案例匯入依賴
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version></dependency>
簡單案例如下
public class QuartzTest { // 你需要在start和shutdown之間執行你的任務。 public static void main(String[] args) { try { // 從工廠中獲取Scheduler示例 Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); // 開始 scheduler.start(); // 定義Job,並將其繫結到HelloJob類中 JobDetail job = JobBuilder.newJob(HelloJob.class) .withIdentity("job1", "group1") // name 和 group .usingJobData("username", "天喬巴夏") // 置入JobDataMap .usingJobData("age", "20") .withDescription("desc-demo") .build(); // 觸發Job執行,每40s執行一次 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group1") .startNow() // 立即開始 .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(40) .repeatForever()) .build(); // 告訴 quartz 使用trigger來排程job scheduler.scheduleJob(job, trigger); // 關閉,執行緒終止 scheduler.shutdown(); } catch (SchedulerException se) { se.printStackTrace(); } }}@Slf4j@NoArgsConstructorpublic class HelloJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 從context中獲取屬性 JobDetail jobDetail = context.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); JobKey key = jobDetail.getKey(); Class<? extends Job> jobClass = jobDetail.getJobClass(); String description = jobDetail.getDescription(); String username = jobDataMap.getString("username"); int age = jobDataMap.getIntValue("age"); log.info("\nJobKey : {},\n JobClass : {},\n JobDesc : {},\n username : {},\n age : {}", key, jobClass.getName(), description, username, age); }}
啟動測試,列印日誌如下:
01:23:12.406 [main] INFO org.quartz.impl.StdSchedulerFactory - Using default implementation for ThreadExecutor01:23:12.414 [main] INFO org.quartz.simpl.SimpleThreadPool - Job execution threads will use class loader of thread: main01:23:12.430 [main] INFO org.quartz.core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl01:23:12.430 [main] INFO org.quartz.core.QuartzScheduler - Quartz Scheduler v.2.3.2 created.01:23:12.432 [main] INFO org.quartz.simpl.RAMJobStore - RAMJobStore initialized.01:23:12.433 [main] INFO org.quartz.core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.3.2) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads. Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.01:23:12.433 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'01:23:12.433 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.201:23:12.434 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.01:23:12.434 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 0 triggers01:23:12.443 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers01:23:12.445 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=com.hyhwky.HelloJob01:23:12.451 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 0 triggers01:23:12.452 [DefaultQuartzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job101:23:12.452 [DefaultQuartzScheduler_Worker-1] INFO com.hyhwky.HelloJob - JobKey : group1.job1, JobClass : com.hyhwky.HelloJob, JobDesc : desc-demo, username : 天喬巴夏, age : 20
我們可以看到quartz已經被初始化了,初始化配置如下,在org\quartz-scheduler\quartz\2.3.2\quartz-2.3.2.jar!\org\quartz\quartz.properties
# 排程器配置org.quartz.scheduler.instanceName: DefaultQuartzSchedulerorg.quartz.scheduler.rmi.export: falseorg.quartz.scheduler.rmi.proxy: falseorg.quartz.scheduler.wrapJobExecutionInUserTransaction: false# 執行緒池配置org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount: 10org.quartz.threadPool.threadPriority: 5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true# 儲存配置org.quartz.jobStore.misfireThreshold: 60000 #trigger 容忍時間60sorg.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
更多的配置:Quartz Configuration Reference
Job例項和JobDetailJob和JobDetail
Job是正在執行的作業例項,JobDetail是作業定義。一個Job可以建立多個JobDetail,擁有不同的JobDataMap。這樣定義有什麼好處呢?舉個例子吧,假設現在你定義了一個類實現了Job介面,比如:SendEmailJob。如果你希望根據使用者的姓名,選擇指定的人傳送,那麼你可以透過JobDataMap繫結引數傳遞進JobDetail中,也就是說我們需要建立兩個不同的JobDetail,比如:SendEmailToSummerday和SendEmailToTQBX,他們擁有各自獨立的JobDataMap,實現更加靈活。
Job的State和Concurrencyhttps://blog.csdn.net/fly_captain/article/details/83029440
@DisallowConcurrentExecution該註解標註在Job類上,意思是不能併發從同一個JobDetail定義的多個例項,但可以同時執行多個不同的JobDetail定義的例項。
拿上面的例子繼續舉例,假設SendEmailJob標註了此註解,表明同一時間可以同時執行SendEmailToSummerday和SendEmailToTQBX,因為他們是不同的JobDetail,但是不能同時執行多個SendEmailToSummerday。
@PersistJobDataAfterExecution該註解也標註在Job類上,告訴Scheduler正常執行完Job之後,重新儲存更新一下JobDataMap。一般標註此註解的Job類應當考慮也加上@DisallowConcurrentExecution註解,以避免同時執行Job時出現JobDataMap儲存的競爭。
Trigger常見使用更多例子可以檢視文件,非常詳細:SimpleTrigger 和 CronTrigger
構建一個觸發器,該觸發器將立即觸發,然後每五分鐘重複一次,直到小時 22:00:
import static org.quartz.TriggerBuilder.*;import static org.quartz.SimpleScheduleBuilder.*;import static org.quartz.DateBuilder.*: SimpleTrigger trigger = (SimpleTrigger) newTrigger() .withIdentity("trigger7", "group1") .withSchedule(simpleSchedule() .withIntervalInMinutes(5) .repeatForever()) .endAt(dateOf(22, 0, 0)) .build();
構建一個觸發器,該觸發器將在週三上午 10:42 觸發,在系統預設值以外的時區中:
import static org.quartz.TriggerBuilder.*;import static org.quartz.CronScheduleBuilder.*;import static org.quartz.DateBuilder.*: trigger = newTrigger() .withIdentity("trigger3", "group1") .withSchedule(cronSchedule("0 42 10 ? * WED")) // [秒] [分] [時] [月的第幾天] [月] [一星期的第幾天] [年(可選)] .inTimeZone(TimeZone.getTimeZone("America/Los_Angeles")) .forJob(myJobKey) .build();
Quartz儲存與持久化
Job的持久化是非常重要的,如果Job不能持久化,一旦不再有與之關聯的Trigger,他就會自動從排程程式中被刪除。
小結Job儲存器的型別:
具體使用方法:http://www.quartz-scheduler.org/documentation/quartz-2.2.2/tutorials/tutorial-lesson-09.html
以上就是要與大家分享的內容了
原文連結:https://www.cnblogs.com/summerday152/p/14192845.html