小記:Quartz 當 Job 執行時間超過觸發間隔時間時所發生的狀況

一個普通的 Job 實現以下:併發

public class Job1 : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        Console.WriteLine(DateTime.Now + ": Job1" + m);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        var props = new NameValueCollection();
        //使用簡單線程池
        props["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
        //最大線程數
        props["quartz.threadPool.threadCount"] = "10";
        //線程優先級:正常
        props["quartz.threadPool.threadPriority"] = "Normal";
        //初始化調度器
        IScheduler scheduler = new StdSchedulerFactory(props).GetScheduler();

        //Cron 觸發器,每隔 1 秒觸發一次
        ITrigger trig = TriggerBuilder.Create().WithCronSchedule("0/1 * * * * ?").Build();
        //將做業 Job1 加入調度計劃中
        scheduler.ScheduleJob(JobBuilder.Create<Job1>().Build(), trig);
        //開始執行
        scheduler.Start();
        
        Console.ReadLine();
        scheduler.Shutdown();
    }
}

執行結果以下:能夠看到,Job1 準確的每隔 1 秒執行一次框架

如今問題來了:若是 Job1 中的操做執行時間很長,超過了間隔時間 1 秒,會發生什麼狀況?代碼以下:ui

public class Job1 : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        Console.WriteLine(DateTime.Now + ": Job1" + m);
        //等待 5 秒
        Thread.Sleep(5000);
    }
}

執行結果以下:spa

咱們會發現,Quartz 仍然會按照咱們設定的每隔 1 秒觸發一次。線程

這是由於默認狀況下,當Job執行時間超過間隔時間時,調度框架爲了能讓任務按照咱們預約的時間間隔執行,會立刻啓用新的線程執行任務code

 

若咱們但願當前任務執行完以後再執行下一輪任務,也就是不要併發執行任務,該如何解決呢?orm

第一種方法:設置 quartz.threadPool.threadCount 最大線程數爲 1。這樣到了第二次執行任務時,若當前還沒執行完,調度器想新開一個線程執行任務,但咱們卻設置了最大線程數爲 1 個(即:沒有足夠的線程提供給調度器),則調度器會等待當前任務執行完以後,再當即調度執行下一次任務。(注意:此方法僅適用於Quartz中僅有一個Job,若是有多個Job,會影響其餘Job的執行)blog

第二種方法:在 Job 類的頭部加上 [DisallowConcurrentExecution],表示禁用併發執行。(推薦使用此方法)string

//不容許此 Job 併發執行任務(禁止新開線程執行)
[DisallowConcurrentExecution]
public class Job1 : IJob
{
}
相關文章
相關標籤/搜索