欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
用 Quartz 進(jìn)行作業(yè)調度

Michael Lipton (mwlipton@us.ibm.com), 軟件工程師, IBM
Soobaek Jang (sjang@us.ibm.com), IT 架構師/集成師, IBM

2006 年 12 月 28 日

Quartz 是個(gè)開(kāi)放源碼項目,提供了豐富的作業(yè)調度集。在這篇文章中,軟件工程師 Michael Lipton 和 IT 架構師 Soobaek Jang 對 Quartz API 進(jìn)行了介紹,從對框架的一般概述開(kāi)始,并以一系列展示 Quart 基本特性的代碼示例作為結束。在閱讀完本文并看過(guò)代碼示例后,您應當能夠把 Quartz 的基本特性應用到任何 Java? 應用程序中。

現代的 Web 應用程序框架在范圍和復雜性方面都有所發(fā)展,應用程序的每個(gè)底層組件也必須相應地發(fā)展。作業(yè)調度是現代系統中對 Java 應用程序的一般要求,而且也是對 Java 開(kāi)發(fā)人員一貫的要求。雖然目前的調度技術(shù)比起原始的數據庫觸發(fā)器標志和獨立的調度器線(xiàn)程來(lái)說(shuō),已經(jīng)發(fā)展了許多,但是作業(yè)調度仍然不是個(gè)小問(wèn)題。對這個(gè)問(wèn)題最合適的解決方案就是來(lái)自 OpenSymphony 的 Quartz API。

Quartz 是個(gè)開(kāi)源的作業(yè)調度框架,為在 Java 應用程序中進(jìn)行作業(yè)調度提供了簡(jiǎn)單卻強大的機制。Quartz 允許開(kāi)發(fā)人員根據時(shí)間間隔(或天)來(lái)調度作業(yè)。它實(shí)現了作業(yè)和觸發(fā)器的多對多關(guān)系,還能把多個(gè)作業(yè)與不同的觸發(fā)器關(guān)聯(lián)。整合了 Quartz 的應用程序可以重用來(lái)自不同事件的作業(yè),還可以為一個(gè)事件組合多個(gè)作業(yè)。雖然可以通過(guò)屬性文件(在屬性文件中可以指定 JDBC 事務(wù)的數據源、全局作業(yè)和/或觸發(fā)器偵聽(tīng)器、插件、線(xiàn)程池,以及更多)配置 Quartz,但它根本沒(méi)有與應用程序服務(wù)器的上下文或引用集成在一起。結果就是作業(yè)不能訪(fǎng)問(wèn) Web 服務(wù)器的內部函數;例如,在使用 WebSphere 應用服務(wù)器時(shí),由 Quartz 調度的作業(yè)并不能影響服務(wù)器的動(dòng)態(tài)緩存和數據源。

本文使用一系列代碼示例介紹 Quartz API,演示它的機制,例如作業(yè)、觸發(fā)器、作業(yè)倉庫和屬性。

入門(mén)

要開(kāi)始使用 Quartz,需要用 Quartz API 對項目進(jìn)行配置。步驟如下:

  1. 下載 Quartz API。
  2. 解壓縮并把 quartz-x.x.x.jar 放在項目文件夾內,或者把文件放在項目的類(lèi)路徑中。
  3. 把 core 和/或 optional 文件夾中的 jar 文件放在項目的文件夾或項目的類(lèi)路徑中。
  4. 如果使用 JDBCJobStore,把所有的 JDBC jar 文件放在項目的文件夾或項目的類(lèi)路徑中。

為了方便讀者,我已經(jīng)把所有必要的文件,包括 DB2 JDBC 文件,編譯到一個(gè) zip 文件中。請參閱 下載 小節下載代碼。

現在來(lái)看一下 Quartz API 的主要組件。





回頁(yè)首


作業(yè)和觸發(fā)器

Quartz 調度包的兩個(gè)基本單元是作業(yè)和觸發(fā)器。作業(yè) 是能夠調度的可執行任務(wù),觸發(fā)器 提供了對作業(yè)的調度。雖然這兩個(gè)實(shí)體很容易合在一起,但在 Quartz 中將它們分離開(kāi)來(lái)是有原因的,而且也很有益處。

通過(guò)把要執行的工作與它的調度分開(kāi),Quartz 允許在不丟失作業(yè)本身或作業(yè)的上下文的情況下,修改調度觸發(fā)器。而且,任何單個(gè)的作業(yè)都可以有多個(gè)觸發(fā)器與其關(guān)聯(lián)。





回頁(yè)首


示例 1:作業(yè)

通過(guò)實(shí)現 org.quartz.job 接口,可以使 Java 類(lèi)變成可執行的。清單 1 提供了 Quartz 作業(yè)的一個(gè)示例。這個(gè)類(lèi)用一條非常簡(jiǎn)單的輸出語(yǔ)句覆蓋了 execute(JobExecutionContext context) 方法。這個(gè)方法可以包含我們想要執行的任何代碼(所有的代碼示例都基于 Quartz 1.5.2,它是編寫(xiě)這篇文章時(shí)的穩定發(fā)行版)。


清單 1. SimpleQuartzJob.java
                        package com.ibm.developerworks.quartz;
                        import java.util.Date;
                        import org.quartz.Job;
                        import org.quartz.JobExecutionContext;
                        import org.quartz.JobExecutionException;
                        public class SimpleQuartzJob implements Job {
                        public SimpleQuartzJob() {
                        }
                        public void execute(JobExecutionContext context) throws JobExecutionException {
                        System.out.println("In SimpleQuartzJob - executing its JOB at "
                        + new Date() + " by " + context.getTrigger().getName());
                        }
                        }
                        

請注意,execute 方法接受一個(gè) JobExecutionContext 對象作為參數。這個(gè)對象提供了作業(yè)實(shí)例的運行時(shí)上下文。特別地,它提供了對調度器和觸發(fā)器的訪(fǎng)問(wèn),這兩者協(xié)作來(lái)啟動(dòng)作業(yè)以及作業(yè)的 JobDetail 對象的執行。Quartz 通過(guò)把作業(yè)的狀態(tài)放在 JobDetail 對象中并讓 JobDetail 構造函數啟動(dòng)一個(gè)作業(yè)的實(shí)例,分離了作業(yè)的執行和作業(yè)周?chē)臓顟B(tài)。JobDetail 對象儲存作業(yè)的偵聽(tīng)器、群組、數據映射、描述以及作業(yè)的其他屬性。





回頁(yè)首


示例 2:簡(jiǎn)單觸發(fā)器

觸發(fā)器可以實(shí)現對任務(wù)執行的調度。Quartz 提供了幾種不同的觸發(fā)器,復雜程度各不相同。清單 2 中的 SimpleTrigger 展示了觸發(fā)器的基礎:


清單 2. SimpleTriggerRunner.java
                        public void task() throws SchedulerException
                        {
                        // Initiate a Schedule Factory
                        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
                        // Retrieve a scheduler from schedule factory
                        Scheduler scheduler = schedulerFactory.getScheduler();
                        // current time
                        long ctime = System.currentTimeMillis();
                        // Initiate JobDetail with job name, job group, and executable job class
                        JobDetail jobDetail =
                        new JobDetail("jobDetail-s1", "jobDetailGroup-s1", SimpleQuartzJob.class);
                        // Initiate SimpleTrigger with its name and group name
                        SimpleTrigger simpleTrigger =
                        new SimpleTrigger("simpleTrigger", "triggerGroup-s1");
                        // set its start up time
                        simpleTrigger.setStartTime(new Date(ctime));
                        // set the interval, how often the job should run (10 seconds here)
                        simpleTrigger.setRepeatInterval(10000);
                        // set the number of execution of this job, set to 10 times.
                        // It will run 10 time and exhaust.
                        simpleTrigger.setRepeatCount(100);
                        // set the ending time of this job.
                        // We set it for 60 seconds from its startup time here
                        // Even if we set its repeat count to 10,
                        // this will stop its process after 6 repeats as it gets it endtime by then.
                        //simpleTrigger.setEndTime(new Date(ctime + 60000L));
                        // set priority of trigger. If not set, the default is 5
                        //simpleTrigger.setPriority(10);
                        // schedule a job with JobDetail and Trigger
                        scheduler.scheduleJob(jobDetail, simpleTrigger);
                        // start the scheduler
                        scheduler.start();
                        }
                        

清單 2 開(kāi)始時(shí)實(shí)例化一個(gè) SchedulerFactory,獲得此調度器。就像前面討論過(guò)的,創(chuàng )建 JobDetail 對象時(shí),它的構造函數要接受一個(gè) Job 作為參數。顧名思義,SimpleTrigger 實(shí)例相當原始。在創(chuàng )建對象之后,設置幾個(gè)基本屬性以立即調度任務(wù),然后每 10 秒重復一次,直到作業(yè)被執行 100 次。

還有其他許多方式可以操縱 SimpleTrigger。除了指定重復次數和重復間隔,還可以指定作業(yè)在特定日歷時(shí)間執行,只需給定執行的最長(cháng)時(shí)間或者優(yōu)先級(稍后討論)。執行的最長(cháng)時(shí)間可以覆蓋指定的重復次數,從而確保作業(yè)的運行不會(huì )超過(guò)最長(cháng)時(shí)間。





回頁(yè)首


示例 3: Cron 觸發(fā)器

CronTrigger 支持比 SimpleTrigger 更具體的調度,而且也不是很復雜?;?cron 表達式,CronTrigger 支持類(lèi)似日歷的重復間隔,而不是單一的時(shí)間間隔 —— 這相對 SimpleTrigger 而言是一大改進(jìn)。

Cron 表達式包括以下 7 個(gè)字段:

  • 小時(shí)
  • 月內日期
  • 周內日期
  • 年(可選字段)

特殊字符

Cron 觸發(fā)器利用一系列特殊字符,如下所示:

  • 反斜線(xiàn)(/)字符表示增量值。例如,在秒字段中“5/15”代表從第 5 秒開(kāi)始,每 15 秒一次。

  • 問(wèn)號(?)字符和字母 L 字符只有在月內日期和周內日期字段中可用。問(wèn)號表示這個(gè)字段不包含具體值。所以,如果指定月內日期,可以在周內日期字段中插入“?”,表示周內日期值無(wú)關(guān)緊要。字母 L 字符是 last 的縮寫(xiě)。放在月內日期字段中,表示安排在當月最后一天執行。在周內日期字段中,如果“L”單獨存在,就等于“7”,否則代表當月內周內日期的最后一個(gè)實(shí)例。所以“0L”表示安排在當月的最后一個(gè)星期日執行。

  • 在月內日期字段中的字母(W)字符把執行安排在最靠近指定值的工作日。把“1W”放在月內日期字段中,表示把執行安排在當月的第一個(gè)工作日內。

  • 井號(#)字符為給定月份指定具體的工作日實(shí)例。把“MON#2”放在周內日期字段中,表示把任務(wù)安排在當月的第二個(gè)星期一。

  • 星號(*)字符是通配字符,表示該字段可以接受任何可能的值。

所有這些定義看起來(lái)可能有些嚇人,但是只要幾分鐘練習之后,cron 表達式就會(huì )顯得十分簡(jiǎn)單。

清單 3 顯示了 CronTrigger 的一個(gè)示例。請注意 SchedulerFactory、SchedulerJobDetail 的實(shí)例化,與 SimpleTrigger 示例中的實(shí)例化是相同的。在這個(gè)示例中,只是修改了觸發(fā)器。這里指定的 cron 表達式(“0/5 * * * * ?”)安排任務(wù)每 5 秒執行一次。


清單 3. CronTriggerRunner.java
                        public void task() throws SchedulerException
                        {
                        // Initiate a Schedule Factory
                        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
                        // Retrieve a scheduler from schedule factory
                        Scheduler scheduler = schedulerFactory.getScheduler();
                        // current time
                        long ctime = System.currentTimeMillis();
                        // Initiate JobDetail with job name, job group, and executable job class
                        JobDetail jobDetail =
                        new JobDetail("jobDetail2", "jobDetailGroup2", SimpleQuartzJob.class);
                        // Initiate CronTrigger with its name and group name
                        CronTrigger cronTrigger = new CronTrigger("cronTrigger", "triggerGroup2");
                        try {
                        // setup CronExpression
                        CronExpression cexp = new CronExpression("0/5 * * * * ?");
                        // Assign the CronExpression to CronTrigger
                        cronTrigger.setCronExpression(cexp);
                        } catch (Exception e) {
                        e.printStackTrace();
                        }
                        // schedule a job with JobDetail and Trigger
                        scheduler.scheduleJob(jobDetail, cronTrigger);
                        // start the scheduler
                        scheduler.start();
                        }
                        





回頁(yè)首


高級 Quartz

如上所示,只用作業(yè)和觸發(fā)器,就能訪(fǎng)問(wèn)大量的功能。但是,Quartz 是個(gè)豐富而靈活的調度包,對于愿意研究它的人來(lái)說(shuō),它還提供了更多功能。下一節討論 Quartz 的一些高級特性。





回頁(yè)首


作業(yè)倉庫

Quartz 提供了兩種不同的方式用來(lái)把與作業(yè)和觸發(fā)器有關(guān)的數據保存在內存或數據庫中。第一種方式是 RAMJobStore 類(lèi)的實(shí)例,這是默認設置。這個(gè)作業(yè)倉庫最易使用,而且提供了最佳性能,因為所有數據都保存在內存中。這個(gè)方法的主要不足是缺乏數據的持久性。因為數據保存在 RAM 中,所以應用程序或系統崩潰時(shí),所有信息都會(huì )丟失。

為了修正這個(gè)問(wèn)題,Quartz 提供了 JDBCJobStore。顧名思義,作業(yè)倉庫通過(guò) JDBC 把所有數據放在數據庫中。數據持久性的代價(jià)就是性能降低和復雜性的提高。

設置 JDBCJobStore

在前面的示例中,已經(jīng)看到了 RAMJobStore 實(shí)例的工作情況。因為它是默認的作業(yè)倉庫,所以顯然不需要額外設置就能使用它。但是,使用 JDBCJobStore 需要一些初始化。

在應用程序中設置使用 JDBCJobStore 需要兩步:首先必須創(chuàng )建作業(yè)倉庫使用的數據庫表。 JDBCJobStore 與所有主流數據庫都兼容,而且 Quartz 提供了一系列創(chuàng )建表的 SQL 腳本,能夠簡(jiǎn)化設置過(guò)程??梢栽?Quartz 發(fā)行包的 “docs/dbTables”目錄中找到創(chuàng )建表的 SQL 腳本。第二,必須定義一些屬性,如表 1 所示:


表 1. JDBCJobStore 屬性
屬性名稱(chēng)
org.quartz.jobStore.class org.quartz.impl.jdbcjobstore.JobStoreTX (or JobStoreCMT)
org.quartz.jobStore.tablePrefix QRTZ_ (optional, customizable)
org.quartz.jobStore.driverDelegateClass org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource qzDS (customizable)
org.quartz.dataSource.qzDS.driver com.ibm.db2.jcc.DB2Driver (could be any other database driver)
org.quartz.dataSource.qzDS.url jdbc:db2://localhost:50000/QZ_SMPL (customizable)
org.quartz.dataSource.qzDS.user db2inst1 (place userid for your own db)
org.quartz.dataSource.qzDS.password pass4dbadmin (place your own password for user)
org.quartz.dataSource.qzDS.maxConnections 30

清單 4 展示了 JDBCJobStore 提供的數據持久性。就像在前面的示例中一樣,先從初始化 SchedulerFactoryScheduler 開(kāi)始。然后,不再需要初始化作業(yè)和觸發(fā)器,而是要獲取觸發(fā)器群組名稱(chēng)列表,之后對于每個(gè)群組名稱(chēng),獲取觸發(fā)器名稱(chēng)列表。請注意,每個(gè)現有的作業(yè)都應當用 Scheduler.reschedule() 方法重新調度。僅僅重新初始化在先前的應用程序運行時(shí)終止的作業(yè),不會(huì )正確地裝載觸發(fā)器的屬性。


清單 4. JDBCJobStoreRunner.java
                        public void task() throws SchedulerException
                        {
                        // Initiate a Schedule Factory
                        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
                        // Retrieve a scheduler from schedule factory
                        Scheduler scheduler = schedulerFactory.getScheduler();
                        String[] triggerGroups;
                        String[] triggers;
                        triggerGroups = scheduler.getTriggerGroupNames();
                        for (int i = 0; i < triggerGroups.length; i++) {
                        triggers = scheduler.getTriggerNames(triggerGroups[i]);
                        for (int j = 0; j < triggers.length; j++) {
                        Trigger tg = scheduler.getTrigger(triggers[j], triggerGroups[i]);
                        if (tg instanceof SimpleTrigger && tg.getName().equals("simpleTrigger")) {
                        ((SimpleTrigger)tg).setRepeatCount(100);
                        // reschedule the job
                        scheduler.rescheduleJob(triggers[j], triggerGroups[i], tg);
                        // unschedule the job
                        //scheduler.unscheduleJob(triggersInGroup[j], triggerGroups[i]);
                        }
                        }
                        }
                        // start the scheduler
                        scheduler.start();
                        }
                        

運行 JDBCJobStore

在第一次運行示例時(shí),觸發(fā)器在數據庫中初始化。圖 1 顯示了數據庫在觸發(fā)器初始化之后但尚未擊發(fā)之前的情況。所以,基于 清單 4 中的 setRepeatCount() 方法,將 REPEAT_COUNT 設為 100,而 TIMES_TRIGGERED 是 0。在應用程序運行一段時(shí)間之后,應用程序停止。


圖 1. 使用 JDBCJobStore 時(shí)數據庫中的數據(運行前)

圖 2 顯示了數據庫在應用程序停止后的情況。在這個(gè)圖中,TIMES_TRIGGERED 被設為 19,表示作業(yè)運行的次數。


圖 2. 同一數據在 19 次迭代之后

當再次啟動(dòng)應用程序時(shí),REPEAT_COUNT 被更新。這在圖 3 中很明顯。在圖 3 中可以看到 REPEAT_COUNT 被更新為 81,所以新的 REPEAT_COUNT 等于前面的 REPEAT_COUNT 值減去前面的 TIMES_TRIGGERED 值。而且,在圖 3 中還看到新的 TIMES_TRIGGERED 值是 7,表示作業(yè)從應用程序重新啟動(dòng)以來(lái),又觸發(fā)了 7 次。


圖 3. 第 2 次運行 7 次迭代之后的數據

當再次停止應用程序之后,REPEAT_COUNT 值再次更新。如圖 4 所示,應用程序已經(jīng)停止,還沒(méi)有重新啟動(dòng)。同樣,REPEAT_COUNT 值更新成前一個(gè) REPEAT_COUNT 值減去前一個(gè) TIMES_TRIGGERED 值。


圖 4. 再次運行觸發(fā)器之前的初始數據





回頁(yè)首


使用屬性

正如在使用 JDBCJobStore 時(shí)看到的,可以用許多屬性來(lái)調整 Quartz 的行為。應當在 quartz.properties 文件中指定這些屬性。請參閱 參考資料 獲得可以配置的屬性的列表。清單 5 顯示了用于 JDBCJobStore 示例的屬性:


清單 5. quartz.properties
                        org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
                        org.quartz.threadPool.threadCount = 10
                        org.quartz.threadPool.threadPriority = 5
                        org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
                        # Using RAMJobStore
                        ## if using RAMJobStore, please be sure that you comment out the following
                        ## - org.quartz.jobStore.tablePrefix,
                        ## - org.quartz.jobStore.driverDelegateClass,
                        ## - org.quartz.jobStore.dataSource
                        #org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
                        # Using JobStoreTX
                        ## Be sure to run the appropriate script(under docs/dbTables) first to create tables
                        org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
                        # Configuring JDBCJobStore with the Table Prefix
                        org.quartz.jobStore.tablePrefix = QRTZ_
                        # Using DriverDelegate
                        org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
                        # Using datasource
                        org.quartz.jobStore.dataSource = qzDS
                        # Define the datasource to use
                        org.quartz.dataSource.qzDS.driver = com.ibm.db2.jcc.DB2Driver
                        org.quartz.dataSource.qzDS.URL = jdbc:db2://localhost:50000/dbname
                        org.quartz.dataSource.qzDS.user = dbuserid
                        org.quartz.dataSource.qzDS.password = password
                        org.quartz.dataSource.qzDS.maxConnections = 30
                        





回頁(yè)首


結束語(yǔ)

Quartz 作業(yè)調度框架所提供的 API 在兩方面都表現極佳:既全面強大,又易于使用。Quartz 可以用于簡(jiǎn)單的作業(yè)觸發(fā),也可以用于復雜的 JDBC 持久的作業(yè)存儲和執行。OpenSymphony 在開(kāi)放源碼世界中成功地填補了一個(gè)空白,過(guò)去繁瑣的作業(yè)調度現在對開(kāi)發(fā)人員來(lái)說(shuō)不過(guò)是小菜一碟。






回頁(yè)首


下載

描述 名字 大小 下載方法
帶有依賴(lài) jar 的基于 Quartz 的示例 Java 代碼 j-quartz-withJars.zip 3173KB HTTP
不帶依賴(lài) jar 的基于 Quartz 的示例 Java 代碼 j-quartz-noJars.zip 10KB HTTP
關(guān)于下載方法的信息
Get Adobe? Reader?


參考資料

學(xué)習

獲得產(chǎn)品和技術(shù)
  • Download Quartz:Java 應用程序的開(kāi)放源碼作業(yè)調度解決方案。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Quartz使用示例總結
一個(gè)簡(jiǎn)單的使用Quartz和Oozie調度作業(yè)給大數據計算平臺執行
Quartz使用入門(mén)
Quartz.NET作業(yè)調度框架詳解 - leeolevis - 博客園
Quartz使用總結
Quartz從入門(mén)到進(jìn)階
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久