1.DisallowConcurrentExecution
加到IJob實現類上,主要防止相同JobDetail並發執行。
簡單來說,現在有一個實現了IJob接口的CallJob,觸發器設置的時間是每5s執行一次,但是由於執行過程的時間大於5s,在Quartz scheduler的下一次執行時間到了,那么就會開啟另外一個線程執行CallJob,說着有點繞,來點代碼吧。
1 Common.Logging.LogManager.Adapter = new Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter { Level = Common.Logging.LogLevel.Info }; 2 3 IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler(); 4 scheduler.Start(); 5 IJobDetail job = JobBuilder.Create<CallJob>().WithIdentity("calljob", "call")
.UsingJobData("hello", 0)//先忽略,第二個特性用到
.Build(); 6 //觸發器 7 ITrigger trigger = TriggerBuilder.Create().WithIdentity("calljobtrigger", "call").StartNow().WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever()).Build(); 8 scheduler.ScheduleJob(job, trigger); 9 Thread.Sleep(TimeSpan.FromSeconds(3000)); 10 scheduler.Shutdown();
1 public class CallJob : IJob 2 { 3 4 public void Execute(IJobExecutionContext context) 5 { 6 int i = (int)context.JobDetail.JobDataMap["hello"];//先忽略,第二個特性用到 7 Console.WriteLine("=====call======"+(i)); 8 Console.WriteLine("call【" + Thread.CurrentThread.ManagedThreadId + "】" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 9 i++; 10 context.JobDetail.JobDataMap.Put("hello", i);//先忽略,第二個特性用到 11 Thread.Sleep(8000); 12 Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "call執行完畢【" + Thread.CurrentThread.ManagedThreadId); 13 14 } 15 }
從代碼中可以看到我們設置的trrigger是5秒執行一次,在CallJob的Execute中,讓線程sleep 8s,這樣就能模擬剛才說的情況了,先看下不加DisallowConcurrentExecution的結果
第一張圖是不加特性的,第二張圖是加上特性的。圖一中不難發現,線程10在休眠的時候,由於scheduler規划的trigger已經觸發,會立即執行,不去管上次任務是否執行完成,從而出現了同一個Job並行。圖二就不會出現並行的情況,當第一次任務還沒有執行完成的時候,即使規划的trigger的觸發時間到了也不會立即執行,而是等待上次任務完成再執行,依次順延,保證了相同JobDetail串行。說明一下DisallowConcurrentExecution是禁止相同JobDetail同時執行,而不是禁止多個不同JobDetail同時執行。建議加上該特性,防止由於任務執行時間太長,長時間占用資源,導致其它任務堵塞。
2.PersistJobDataAfterExecution
加到IJob實現類上,主要表示當正常執行完Job后, JobDataMap中的數據應該被改動, 以被下一次調用時用。還是上面的代碼,只是將特性DisallowConcurrentExecution換成了PersistJobDataAfterExecution,特別注意代碼中【先忽略】部分。
當不使用PersistJobDataAfterExecution特性時,每次取出來的hello鍵值對的value始終都是0,也就是說每次執行 JobDataMap中的數據都是全新的一份,加上特性PersistJobDataAfterExecution之后,就會出現數據共享。沒加特性的結果可以看上圖,加上之后看下圖。
注意當使用【PersistJobDataAfterExecution】特性時, 為了避免並發時, 存儲數據造成混亂, 強烈建議把【DisallowConcurrentExecution】特性也加上。
本人很菜,歡迎拍磚。