覚えたら書く

IT関係のデベロッパとして日々覚えたことを書き残したいです。twitter: @yyoshikaw

Quartz - Jobを重複して実行しないようにする

Javaで簡単に定期処理を行うためのライブラリであるQuartzの紹介エントリを書きました。

その際に、100ミリ秒間隔で処理を行う例を書きましたが、実は対象のジョブが実行開始して100ミリ秒以内に処理をおえられない場合は、同一のジョブがさらに実行される状態となります。
(前のジョブが完了していてもいなくても、次のジョブが強制的に開始される ということです)


その動きについて以下確認します。

■サンプルコード

たとえば、以下のようなログ出力して500ミリ秒スリープする処理を行うジョブを定義します。

import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@Slf4j
public class MyJob1a implements org.quartz.Job {

    public MyJob1a() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info(">> MyJob1a is execute start.");

        // 処理に時間がかかることを表現するための500msスリープする
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info(">> MyJob1a is execute end.");
    }
}

■実行結果

このジョブを100ミリ秒間隔で実行すると以下のような出力になり、(startのログを見ると)100ミリ秒ごとにジョブが実行されていることが分かります。

2016/12/13 19:28:52.905 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:52.998 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.099 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.199 INFO  [QuartzScheduler_Worker-4] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.298 INFO  [QuartzScheduler_Worker-5] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.398 INFO  [QuartzScheduler_Worker-6] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.406 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.498 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.498 INFO  [QuartzScheduler_Worker-7] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.598 INFO  [QuartzScheduler_Worker-8] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.599 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.698 INFO  [QuartzScheduler_Worker-9] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.699 INFO  [QuartzScheduler_Worker-4] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.798 INFO  [QuartzScheduler_Worker-5] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.798 INFO  [QuartzScheduler_Worker-10] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.898 INFO  [QuartzScheduler_Worker-6] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.898 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:53.998 INFO  [QuartzScheduler_Worker-7] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:53.998 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.098 INFO  [QuartzScheduler_Worker-8] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.098 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.198 INFO  [QuartzScheduler_Worker-9] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.198 INFO  [QuartzScheduler_Worker-4] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.298 INFO  [QuartzScheduler_Worker-10] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.298 INFO  [QuartzScheduler_Worker-5] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.398 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.400 INFO  [QuartzScheduler_Worker-6] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.498 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.498 INFO  [QuartzScheduler_Worker-7] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.598 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.598 INFO  [QuartzScheduler_Worker-8] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.698 INFO  [QuartzScheduler_Worker-9] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.699 INFO  [QuartzScheduler_Worker-4] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.798 INFO  [QuartzScheduler_Worker-5] t.a.q.MyJob1a >> MyJob1a is execute end.
2016/12/13 19:28:54.798 INFO  [QuartzScheduler_Worker-10] t.a.q.MyJob1a >> MyJob1a is execute start.
2016/12/13 19:28:54.898 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1a >> MyJob1a is execute start.


ジョブが重複して実行されても問題ないケースもあるかもしれませんが、重複して実行してほしくない場合もあると思います。

その場合に使用するための、@DisallowConcurrentExecution(org.quartz.DisallowConcurrentExecution)というアノテーションが用意されています。
対象のジョブのクラスにこのアノテーションを付与するだけで重複した実行が行われないようになります。


■サンプルコード

先ほどと同じ内容の処理を行うクラスに@DisallowConcurrentExecutionを付与します

import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution
@Slf4j
public class MyJob1b implements org.quartz.Job {

    public MyJob1b() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
        log.info(">> MyJob1b is execute start.");

        // 処理に時間がかかることを表現するための500msスリープする
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info(">> MyJob1b is execute end.");
    }
}

■実行結果

このジョブを100ミリ秒間隔で実行すると以下のような出力になり、100ミリ秒ごとにジョブが実行されるということが無くなっていることが分かります(ジョブの重複実行が行われない)。

2016/12/13 19:28:10.826 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1b >> MyJob1b is execute start.
2016/12/13 19:28:11.326 INFO  [QuartzScheduler_Worker-1] t.a.q.MyJob1b >> MyJob1b is execute end.
2016/12/13 19:28:11.418 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1b >> MyJob1b is execute start.
2016/12/13 19:28:11.918 INFO  [QuartzScheduler_Worker-2] t.a.q.MyJob1b >> MyJob1b is execute end.
2016/12/13 19:28:12.018 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1b >> MyJob1b is execute start.
2016/12/13 19:28:12.519 INFO  [QuartzScheduler_Worker-3] t.a.q.MyJob1b >> MyJob1b is execute end.
2016/12/13 19:28:12.618 INFO  [QuartzScheduler_Worker-4] t.a.q.MyJob1b >> MyJob1b is execute start.



関連エントリ