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): 【數據庫配置定時】-【結束】