咱們給了scheduler 一個JobDetail 實例,而咱們再建立JobDetail實例的時候,告訴了它咱們的Job的類型,因此,scheduler也是知道咱們job的類型的。併發
每次scheduler在執行Job的時候,在執行job的execute方法以前,都會建立一個咱們job的實例,在execute方法執行結束後,job實例會被GC(回收)ide
這樣就會致使兩個結果,一、必須爲咱們本身的job提供一個無參的構造函數 二、沒法記錄job執行的狀態(兩次execute之間)。函數
那麼問題來了,若是想要記錄job執行狀態,怎麼辦?答案是JobDataMapui
JobDataMap是JobDetail的一個屬性this
JobDataMap其實就是一個Map的實現,能夠當作是map,只是提供了一些更加方便的存取方法。JobDataMap存放的數據必須是可序列化的。spa
JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("job1","jobgroup") .usingJobData("name","張三") .usingJobData("time","2018") .build();
如上代碼,添加了name和time兩個屬性,咱們能夠在Job中獲取到get
@Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("定時任務正在執行" + context.getJobDetail().getJobDataMap().getString("time")); }
若是在咱們本身的Job類中,咱們本身提供了setter方法,setter方法的名稱必須和JobDataMap中屬性名稱相對應,那麼,Quartz的默認JobFactory會自動裝配這些setter方法所對應的Job的屬性值。這就避免了從JobExecutionContext中獲取值得方法。以下it
public class MyJob implements Job { public String time; public void setTime(String time) { this.time = time; } @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("定時任務正在執行" + time); } }
上面兩種從JobDataMap中取值得方法中,第一種方法,Job類代碼簡潔,可是execute中代碼比較繁瑣。io
第二種方法,execute中代碼簡潔了,可是Job類代碼比原來多了。至於怎麼選擇,看本身愛好了。class
因爲JobDetai和Trigger都有JobDataMap,因此,當使用第二種方法時,若是在設置值時,JobDetail和Trigger的JobDataMap有相同的Key,則Trigger的Key會覆蓋JobDetail的Key。同理若是使用JobExecuteContext.getMergeJobDataMap來取值(即兩個JobDataMap合併),那麼,Trigger的Key一樣會覆蓋JobDetail的Key
Job還有兩個註解可使用,通常是成對出現(要麼都使用,要麼都不用)
@DisallowConcurrentExecution 顧名思義,就是不容許多個job同時執行。
@PersistJobDataAfterExecution 每次執行完一個Job後,更新JobDetail的JobDataMap的值。那麼爲了防止併發出現問題,這兩個註解都是同時使用