Quartz框架(五)— 有狀態的job和無狀態job

Quartz框架(一)—Quartz的基本配置
Quartz框架(二)—jobstore數據庫表字段詳解
Quartz框架(三)—任務的並行/串行執行
Quartz框架(四)—misfire處理機制
Quartz框架(五)— 有狀態的job和無狀態job
Quartz框架(六)— Trigger狀態轉換
Quartz框架(七)— Quartz集羣+實戰運用

Job中有一個StatefulJob子接口,代表着有狀態的任務,該接口是一個沒有方法的標籤接口,其目的就是讓Quartz知道任務的類型,以便採用不同的執行方案。

 /* 
 *
 * @deprecated use DisallowConcurrentExecution and/or PersistJobDataAfterExecution annotations instead.
 * 
 * @author James House
 */
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public interface StatefulJob extends Job {

    /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     * 
     * Interface.
     * 
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

}

正如原碼中描述:use DisallowConcurrentExecution and/or PersistJobDataAfterExecution annotations instead.該接口已過時,但是可以使用上面的註解代替。

  • @DisallowConcurrentExecution 不允許併發執行,即JOB爲串行執行。
  • @PersistJobDataAfterExecution 在執行後將JobData持久化。

無狀態任務在執行時,擁有自己的JobDataMap拷貝,對JobData的更改不會影響下次的執行。而有狀態任務共享同一個JobDataMap實例,每次任務執行對JobDataMap所做的更改都會保存下來,後面的執行可以看到這個更改。也就是每次執行任務後都會對後面的執行發生影響。

正因爲這個原因,無狀態的Job可以併發執行,而有狀態的StatefulJob不能併發執行,這意味着如果前次的StatefulJob還沒有執行完畢,下一次的任務將阻塞等待,直到前次任務執行完畢。有狀態任務比無狀態任務需要考慮更多的因素,程序往往擁有更高的複雜度,因此除非必要,應該儘量使用無狀態的Job。

如果Quartz使用了數據庫持久化任務調度信息,無狀態的JobDataMap僅會在Scheduler註冊任務時保持一次,而有狀態任務對應的JobDataMap在每次執行任務後都會進行保存。

Trigger自身也可以擁有一個JobDataMap,其關聯的Job可以通過JobExecutionContext#getTrigger().getJobDataMap()獲取Trigger中的JobDataMap。不管是有狀態還是無狀態的任務,在任務執行期間對Trigger的JobDataMap所做的更改都不會進行持久,也即不會對下次的執行產生影響。

案例測試:

1. 有狀態的Job

@Component
public class TestJob2 extends CustomQuartzJobBean implements StatefulJob {
    private Logger logger = LoggerFactory.getLogger(TestJob2.class);

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String value = jobDataMap.getString("key");
        logger.info("value的值:"+value);
        //設置jobData的值
        jobDataMap.put("key",value + "哈哈");

        logger.info("【數據庫配置定時】-【結束】");
    }
}

執行結果:

2019-07-08 14:32:20,572 INFO [6105] [clusteredScheduler_Worker-6] [] (TestJob2.java:30): value的值:這是一個
2019-07-08 14:32:20,573 INFO [6106] [clusteredScheduler_Worker-6] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】
2019-07-08 14:32:25,020 INFO [10553] [clusteredScheduler_Worker-7] [] (TestJob2.java:30): value的值:這是一個哈哈
2019-07-08 14:32:25,021 INFO [10554] [clusteredScheduler_Worker-7] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】
2019-07-08 14:32:30,013 INFO [15546] [clusteredScheduler_Worker-8] [] (TestJob2.java:30): value的值:這是一個哈哈哈哈
2019-07-08 14:32:30,013 INFO [15546] [clusteredScheduler_Worker-8] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】
2019-07-08 14:32:35,017 INFO [20550] [clusteredScheduler_Worker-9] [] (TestJob2.java:30): value的值:這是一個哈哈哈哈哈哈
2019-07-08 14:32:35,018 INFO [20551] [clusteredScheduler_Worker-9] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】
2019-07-08 14:32:40,015 INFO [25548] [clusteredScheduler_Worker-10] [] (TestJob2.java:30): value的值:這是一個哈哈哈哈哈哈哈哈
2019-07-08 14:32:40,015 INFO [25548] [clusteredScheduler_Worker-10] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】
2019-07-08 14:32:45,016 INFO [30549] [clusteredScheduler_Worker-1] [] (TestJob2.java:30): value的值:這是一個哈哈哈哈哈哈哈哈哈哈
2019-07-08 14:32:45,016 INFO [30549] [clusteredScheduler_Worker-1] [] (TestJob2.java:33): 【數據庫配置定時】-【結束】

2. 無狀態的Job

@Component
public class TestJob2 extends CustomQuartzJobBean {
    private Logger logger = LoggerFactory.getLogger(TestJob2.class);

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String value = jobDataMap.getString("key");
        logger.info("value的值:"+value);
        //設置jobData的值
        jobDataMap.put("key",value + "哈哈");

        logger.info("【數據庫配置定時】-【結束】");
    }
}

執行結果:

2019-07-08 15:05:25,026 INFO [8174] [clusteredScheduler_Worker-2] [] (TestJob2.java:23): value的值:這是一個
2019-07-08 15:05:25,026 INFO [8174] [clusteredScheduler_Worker-2] [] (TestJob2.java:27): 【數據庫配置定時】-【結束】
2019-07-08 15:05:30,017 INFO [13165] [clusteredScheduler_Worker-3] [] (TestJob2.java:23): value的值:這是一個
2019-07-08 15:05:30,017 INFO [13165] [clusteredScheduler_Worker-3] [] (TestJob2.java:27): 【數據庫配置定時】-【結束】
2019-07-08 15:05:35,020 INFO [18168] [clusteredScheduler_Worker-4] [] (TestJob2.java:23): value的值:這是一個
2019-07-08 15:05:35,021 INFO [18169] [clusteredScheduler_Worker-4] [] (TestJob2.java:27): 【數據庫配置定時】-【結束】
2019-07-08 15:05:40,018 INFO [23166] [clusteredScheduler_Worker-5] [] (TestJob2.java:23): value的值:這是一個
2019-07-08 15:05:40,019 INFO [23167] [clusteredScheduler_Worker-5] [] (TestJob2.java:27): 【數據庫配置定時】-【結束】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章