本ページはプロモーションが含まれています

Java入門

Java Quartzの使い方|Spring Boot連携解説

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
9枚
Quartz(Spring Bootでのジョブ実行)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

この記事では、Quartzの基本構造(Job・Trigger・Scheduler)からcron式の設定、Misfire制御、JDBC永続化まで、コピペで動くサンプルコード付きで解説します。Spring Boot 3.x・4.x対応のJobDetail/Trigger定義と、RAMストア・JDBCストアの切り替え方も紹介します。

私はJava歴12年のエンジニアとして、数多くのバッチ処理を設計してきました。

PARTS LIST /目次

Quartzとは何か【Javaのスケジューラ】

Quartz(クォーツ)は、Javaアプリケーションに統合可能な、高機能なジョブスケジューリングライブラリです。

Javaで商用レベルのスケジュール管理を行うなら、Quartzが第一候補です。

理由は、オープンソースでありながら、企業の基幹システムにも耐えうる堅牢性と柔軟性を兼ね備えているからです。

具体的には、数万件のジョブを同時に管理したり、サーバーが落ちても処理を再開させる仕組みを持っています。

単純なタイマー機能を超えた、ジョブ管理のデファクトスタンダードとして広く利用されています。

Quartzの特徴(cron・遅延・再実行制御)

Quartz最大の特徴は、きめ細やかな制御ができる点にあります。

例えば、「毎月25日の朝9時に実行、ただし土日は実行しない」といった複雑なカレンダー制御が可能です。

これを自前で実装しようとすると、膨大な工数とバグのリスクを抱えることになります。

また、処理が失敗した際に自動でリトライさせたり、予定時刻に実行できなかったジョブをあとから実行するか無視するかといった「遅延実行(Misfire)」の制御も設定だけで完結します。

ScheduledExecutorとの違い

Javaには標準でScheduledExecutorServiceという機能がありますが、Quartzとは役割が明確に異なります。

標準機能は、あくまでメモリ上で動く簡易的なタイマーです。アプリケーションを再起動すれば、登録していたスケジュールはすべて消えてしまいます。

対してQuartzは、データベースと連携してスケジュール情報を永続化できます。

これにより、アプリケーションの再起動やクラッシュが発生しても、次回起動時にスケジュールを復元し、止まっていた処理を正しく再開させられます。

Quartzが使われる代表的なユースケース

Quartzは、以下のような「失敗が許されない」あるいは「複雑な条件」が必要なシーンで活躍します。

  • 月次請求処理: 毎月決まった日に大量のデータを集計し、請求書を発行する。
  • メール配信予約: ユーザーが指定した未来の日時にメールを送信する。
  • データ連携: 夜間のシステム負荷が低い時間帯に、外部システムからデータを取り込む。
  • 不要データ削除: 一定期間経過したログファイルや一時データを定期的に掃除する。

Quartzの基本構造【3要素の役割】

Quartzを使いこなすには、主要な3つの登場人物を理解する必要があります。

これらは「何を(Job)」「いつ(Trigger)」「管理する(Scheduler)」という役割分担が明確です。

この構造さえ頭に入れば、設計は驚くほどスムーズになります。

Quartzの3要素の関係(何を・いつ・管理する)
JOB / 何をJob実行したい処理
TRIGGER / いつTrigger実行タイミング
SCHEDULER / 管理するScheduler登録を受け付け、時刻が来たらJobを実行

Job(実行したい処理)

Jobは、実際に実行させたいビジネスロジックそのものです。

具体的には、Jobというインターフェースを実装したクラスを作成し、その中に「メールを送る」「計算する」といった処理を記述します。

Quartzはこのクラスを呼び出す役割に徹するため、処理の中身には関与しません。

Trigger(実行タイミングの設定)

Triggerは、Jobを実行する「引き金」です。

「今すぐ実行」「10秒後に実行」「毎日朝9時に実行」といったスケジュールの定義をここで行います。

一つのJobに対して複数のTriggerを紐付けることも可能です。

例えば、同じレポート作成処理を「毎月末」と「手動リクエスト時」の両方で動かすといった柔軟な運用が実現できます。

Scheduler(管理の司令塔)

Schedulerは、登録されたJobとTriggerを統括する管理コンテナです。

Triggerの設定時間を監視し、時間になると関連付けられたJobをインスタンス化して実行させます。

開発者は「このJobをこのTriggerで動かして」とSchedulerに登録するだけです。

Cron/SimpleTriggerの違い

Triggerには主に2つの種類があり、用途に応じて使い分けます。

  • SimpleTrigger: 「1回だけ実行」や「一定間隔で〇回繰り返す」といった単純なスケジュールに使います。
  • CronTrigger: 「毎週月曜日の10時」のように、カレンダーに基づいた複雑なスケジュールに使います。UNIX系OSのcron式に似た記法(秒フィールドを加えた6〜7フィールド)が利用できます。

Quartzの導入と設定方法

実際にJavaプロジェクトへQuartzを導入する手順を見ていきましょう。

ここでは、ビルドツールとして広く使われているMavenやGradleを用いた設定方法と、最小限のコードで動作させる手順を解説します。

Maven/GradleでQuartz追加

まずはライブラリをプロジェクトに追加します。

Mavenの場合、pom.xmlに以下の依存関係を記述してください。本記事は2026年9月時点の2.5.2(2025年12月リリース)をもとにしています。2.5系はJava 11以上が必要で、jakarta名前空間に移行しています。

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.5.2</version>
</dependency>

Gradleを使用している場合は、build.gradleに以下のように記述します。

implementation 'org.quartz-scheduler:quartz:2.5.2'

最小構成のサンプル(Job+Trigger)

次に、実際に動くコードを書いてみましょう。まずは実行させるJobクラスを作成します。

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Hello, Quartz! 処理を実行しました。");
    }
}

続いて、このJobをスケジュール登録して実行するメインクラスです。

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzExample {
    public static void main(String[] args) {
        try {
            // 1. Schedulerの取得
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            // 2. Schedulerの開始
            scheduler.start();

            // 3. Jobの定義
            JobDetail job = JobBuilder.newJob(HelloJob.class)
                .withIdentity("myJob", "group1")
                .build();

            // 4. Triggerの定義(5秒ごとに実行)
            Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("myTrigger", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(5)
                    .repeatForever())
                .build();

            // 5. スケジュール登録
            scheduler.scheduleJob(job, trigger);

            // 確認のため少し待機(実際はアプリケーションが動き続ける)
            Thread.sleep(20000);

            // 6. 終了
            scheduler.shutdown();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

このコードを実行すると、コンソールに5秒おきにメッセージが表示されます。これがQuartzの最も基本的な形です。

Cron式で柔軟にスケジュールを組む方法

実務ではSimpleTriggerよりも、CronTriggerを使う頻度が高いでしょう。

Cron式は、秒、分、時、日、月、曜日、年(オプション)の順でスペース区切りで記述します。QuartzのCron式は柔軟です。

例を見てみましょう。

  • 0 0 12 * * ? : 毎日お昼の12時に実行
  • 0 15 10 ? * MON-FRI : 平日(月~金)の10時15分に実行
  • 0 0/5 * * * ? : 5分ごとに実行

コードでは以下のように指定します。

Trigger cronTrigger = TriggerBuilder.newTrigger()
    .withIdentity("cronTrigger", "group1")
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 * * ?"))
    .build();

quartz.propertiesの主要設定項目

Quartzの動作はquartz.propertiesファイルで細かく制御できます。クラスパス直下に配置し、以下のような項目を設定します。

  • org.quartz.scheduler.instanceName: スケジューラの識別名(省略時は QuartzScheduler。クラスタリング時は、論理的に同じスケジューラの全ノードで同じ名前にします)
  • org.quartz.threadPool.threadCount: 同時実行可能なジョブ数(デフォルト10)
  • org.quartz.jobStore.class: RAMJobStore(メモリ)またはJobStoreTX(DB永続化)を指定
  • org.quartz.jobStore.driverDelegateClass: DB種類に応じたデリゲートクラス

Spring Bootを使用する場合は、application.properties(またはapplication.yml)のspring.quartz.*で設定します。spring.quartz.properties.org.quartz.threadPool.threadCount=5のように、spring.quartz.properties.の後ろにQuartzのプロパティ名をそのまま書けば渡せます。

Quartzの実践機能【Job/Misfire/永続化】

基本が分かったところで、より実践的な機能について解説します。ここを理解することで、複雑なビジネス要件にも対応できるようになります。

JobDataMapでパラメータを渡す

Jobを実行する際、外部からパラメータを渡したい場合があります。

例えば、同じ「メール送信Job」でも、宛先や件名を動的に変えたい場合などです。この時に使うのがJobDataMapです。

// Job定義時にデータをセット
JobDetail job = JobBuilder.newJob(EmailJob.class)
    .usingJobData("emailAddress", "[email protected]")
    .usingJobData("retryCount", 3)
    .build();

Jobクラス側では、以下のようにデータを受け取ります。

public void execute(JobExecutionContext context) {
    JobDataMap dataMap = context.getJobDetail().getJobDataMap();
    String email = dataMap.getString("emailAddress");
    int retry = dataMap.getInt("retryCount");
    // ロジック...
}

Misfire(実行遅延)が起きた時の動き

サーバーがダウンしていたり、スレッドが枯渇していて予定時刻に処理が開始できなかった状態を「Misfire(ミスファイア)」と呼びます。

Quartzでは、このMisfire発生時にどう振る舞うかを設定できます。

  • FIRE_NOW: 気づいた時点ですぐに実行する。
  • IGNORE_MISFIRES: Misfireとして扱わず、できるだけ早く発火して遅れた分に追いつく。たとえば15秒間隔のSimpleTriggerが5分間遅れると、復帰後に20回続けて発火することがある。
  • RESCHEDULE_NEXT_WITH_EXISTING_COUNT: 遅れた分をスキップし、回数指定などを維持して次へ進む。

これらはTriggerの設定時に指定します。重要なバッチであれば「即時実行」、ログ収集などであれば「スキップ」など、業務要件に合わせて選択します。

私が過去に遭遇したケースでは、深夜バッチが多重起動し、DB負荷でシステム全体が停止したことがあります。

原因はMisfire設定を未指定のまま本番投入したことでした。

デフォルトではQuartzが「賢く」処理しようとしますが、想定外の挙動になることがあります。

明示的にMisfireポリシーを指定する習慣をつけてください。

@DisallowConcurrentExecutionで重複実行を防ぐ方法(旧StatefulJob)

処理に時間がかかり、次の実行タイミングが来てしまうことがあります。

デフォルトでは、Quartzは前の処理が終わっていなくても、時間になれば新しいJobインスタンスを作成して並行実行します。

しかし、データの整合性を保つために「前の処理が終わるまで次は待たせたい」場合があります。

その際は、Jobクラスに@DisallowConcurrentExecutionアノテーションを付与します。

@DisallowConcurrentExecution
public class HeavyBatchJob implements Job {
    // ...
}

これを付けるだけで、同一Job定義の重複実行を自動的に防いでくれます。

処理が長いJobの2回目はどう動くか
時点
デフォルト
@DisallowConcurrentExecution
実行時刻1
1回目のJobが始まる
1回目のJobが始まる
実行時刻21回目はまだ終わっていない
2回目が並行して始まる
2回目は待機
結果
同時に2つ実行
1回目の終了後に2回目(順番)
NOTEデフォルトでは前の処理が終わっていなくても並行実行される。順番に動かしたいJobに付ける。

なお、古い解説記事で見かけるStatefulJobインターフェースはQuartz 2.0以降で非推奨です。現在は@DisallowConcurrentExecution(重複実行の防止)と@PersistJobDataAfterExecution(JobDataMapの変更を次回実行へ引き継ぐ)の2つのアノテーションを使い分けます。

永続化設定(JDBC JobStore)とは?

Quartzの真価は、スケジュール情報をデータベース(DB)に保存できる点にあります。これを「JDBC JobStore」と呼びます。

メモリ上(RAMJobStore)での管理では、アプリケーション停止とともに予約情報が消えますが、DB管理にすることで以下のメリットが生まれます。

  • 障害復旧: サーバーが落ちても、再起動時に未実行のジョブを検知して実行できる。
  • クラスタリング: 複数のサーバーでQuartzを動かし、負荷分散や冗長化が可能になる。

設定はquartz.propertiesファイルで行い、DBにはQuartz専用のテーブルをいくつか作成する必要があります(SQLスクリプトは配布物に同梱されています)。

実務でJDBC JobStoreを導入した際の注意点を共有します。

テーブル名にプレフィックスを付ける設定(org.quartz.jobStore.tablePrefix = QRTZ_)がデフォルトですが、既存DBに追加する場合はテーブル名の衝突に注意してください。

また、初回起動時にテーブルが存在しないとエラーになるため、DDLスクリプトをFlywayやLiquibaseのマイグレーションに組み込んでおくと運用がスムーズです。Spring Bootならspring.quartz.jdbc.initialize-schema=alwaysで起動時にテーブルを作成することもできますが、標準スクリプトは既存のテーブルを削除してから作り直すため、再起動のたびに登録済みのトリガーがすべて消えます。開発環境向けと考えてください。

JobListenerでジョブの実行を監視する

本番運用では、ジョブの開始・終了・失敗を検知して通知を送りたい場面があります。

QuartzのJobListenerインターフェースを実装すると、ジョブ実行のライフサイクルにフックできます。

public class MyJobListener implements JobListener {
    public String getName() { return "MyJobListener"; }

    public void jobToBeExecuted(JobExecutionContext context) {
        System.out.println("ジョブ開始: " + context.getJobDetail().getKey());
    }

    public void jobWasExecuted(JobExecutionContext context, JobExecutionException e) {
        if (e != null) {
            System.err.println("ジョブ失敗: " + e.getMessage());
            // Slack通知やメール送信などの処理
        }
    }

    public void jobExecutionVetoed(JobExecutionContext context) {}
}

Schedulerに登録するだけで、すべてのジョブ実行を横断的に監視できます。障害の早期検知に役立つため、本番環境では必ず設定しておきましょう。

Quartzを本番環境で使う時の注意点

開発環境で動いたからといって、そのまま本番環境へ投入するのは危険です。長期運用を見据えた設計が必要になります。

スケジューラ停止や再起動時の挙動

アプリケーションを停止する際、実行中のジョブをどう扱うかを決めておく必要があります。

scheduler.shutdown(true)を呼び出すと、実行中のジョブが完了するのを待ってから停止します。

これを「グレースフルシャットダウン」と呼びます。一方、引数をfalseにすると即座に停止しますが、データ不整合のリスクがあります。

デプロイ時などは、必ず完了を待つ設定にすることをお勧めします。

DB管理と負荷の考え方(JobStore選択)

JDBC JobStoreを使用する場合、DBへの負荷を考慮しなければなりません。

大量のトリガーが短期間に発火すると、DBへのアクセスが集中します。ロック待ちが発生し、パフォーマンスが低下する原因になります。

数千件以上のジョブを扱う場合は、Quartz用のDBを業務データ用DBとは物理的に分けましょう。

また、スレッドプールのサイズ(同時に実行できるジョブの数)も重要です。デフォルトは10ですが、サーバーのスペックに合わせて適切に調整してください。

ログと例外処理のベストプラクティス

Jobの中で発生した例外(エラー)は、適切にハンドリングしないと闇に葬られます。

Jobクラス内のexecuteメソッドでは、必ずtry-catchブロックで全体を囲みましょう。

エラーが発生したらログを出力し、運用チームが検知できるようにします。

さらに、JobExecutionExceptionをスローする際にsetRefireImmediately(true)を設定すると、Quartzに即座の再実行を指示できます。

単発のエラーで見過ごさず、運用担当者が気づける仕組みを入れておくことが大切です。

QuartzとSpring Bootの連携

現代のJava開発では、Spring Framework(特にSpring Boot)の利用が標準的です。

QuartzはSpringと相性が良く、組み合わせることで開発効率が大幅に上がります。

Spring Boot Starter Quartzの利点

Spring Bootにはspring-boot-starter-quartzというスターターが用意されています。Spring Boot 3.x系に加え、2026年9月時点の最新である4.x系(4.1.1)でも同じスターター名で利用できます。4.0でSpring Boot本体がモジュール分割され、内部的にはspring-boot-quartzモジュールに切り出されましたが、スターターを使う限り依存関係の書き方は変わりません。

これを使うと、面倒なschedulerの初期化や、quartz.propertiesの読み込み、DB接続設定などを自動で行ってくれます。

開発者はJobの中身とスケジュールの定義に集中できるため、生産性が劇的に向上します。

SpringのDIでJobを管理する方法

素のQuartzでは、Jobクラスのインスタンス化はQuartzが行うため、Springの@Autowiredなどが使えません。

しかし、Spring統合機能を使えば、JobクラスもSpringの管理下(Bean)に置くことができます。

これにより、Jobの中からServiceクラスやRepositoryクラスを自由に呼び出すことができ、複雑な業務ロジックもきれいに実装できます。

実際のプロジェクトでは、以下のような構成で管理することが多いです。

  • config/QuartzConfig.java: JobDetail/Triggerの@Bean定義(SchedulerFactoryBeanはSpring Bootが自動構成)
  • job/パッケージ: 各Jobクラスを格納
  • application.ymlのspring.quartz.*: DB接続やスレッドプール設定

この構成にしておくと、新しいJobを追加する際もConfigクラスにBean定義を足すだけで済み、チーム開発でも混乱が起きにくいです。

ここからは、Spring Boot 3.x・4.xで共通して使える最小構成のサンプルです。まずpom.xmlにスターターを追加します。Spring Bootがバージョンを管理するため、<version>の指定は不要です。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

次にJobクラスを作ります。QuartzJobBeanを継承すると、Springが管理するサービスクラスをセッター経由で受け取れます。

// Spring管理のBeanをセッターで受け取れるJob(QuartzJobBeanを継承)
public class ReportJob extends QuartzJobBean {

    private ReportService reportService; // Springのサービスクラス

    public void setReportService(ReportService reportService) {
        this.reportService = reportService;
    }

    @Override
    protected void executeInternal(JobExecutionContext context) {
        reportService.createDailyReport(context.getFireTime());
    }
}

続いて、JobDetail(何を)とTrigger(いつ)を@Beanとして定義します。Spring BootはJobDetail・Trigger・Calendar型のBeanを自動でSchedulerに登録するため、SchedulerFactoryBeanを自分で組み立てる必要はありません。

@Configuration
public class QuartzConfig {

    // JobDetail:「何を」実行するか
    @Bean
    public JobDetail reportJobDetail() {
        return JobBuilder.newJob(ReportJob.class)
                .withIdentity("reportJob")
                .storeDurably()
                .build();
    }

    // Trigger:「いつ」実行するか(毎日9時)
    @Bean
    public Trigger reportJobTrigger(JobDetail reportJobDetail) {
        return TriggerBuilder.newTrigger()
                .forJob(reportJobDetail)
                .withIdentity("reportTrigger")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0 9 * * ?"))
                .build();
    }
}

Spring Boot上でのScheduler・Job・Trigger・JobStoreの関係を図にすると、次のようになります。

Spring BootでのJob・Trigger・Scheduler・JobStoreの関係
JOBDETAIL @BEANJobDetail何を実行するか
TRIGGER @BEANTriggerいつ実行するか(cron等)
SPRING BOOTが自動構成(spring-boot-starter-quartz)Scheduler管理の司令塔
job-store-type は?
memory(既定値)RAMJobStore再起動で消える
jdbcJDBC JobStoreQRTZ_テーブルに永続化
発火時刻に動く流れ
1
SCHEDULERScheduler発火時刻にJobのインスタンスを生成
2
JOBReportJobQuartzJobBean
3
SERVICEReportService

最後にapplication.ymlでJobStoreを選びます。spring.quartz.job-store-typeがmemory(既定値)ならRAMJobStore、jdbcならDB永続化(JDBC JobStore)になります。jdbcを使う場合はDataSourceの設定も必要です。

spring:
  quartz:
    job-store-type: jdbc          # memory(既定・RAMJobStore)または jdbc
    jdbc:
      initialize-schema: always   # 開発用:起動時にQRTZ_テーブルを作り直す(既存データは消える)
    overwrite-existing-jobs: true # 定義変更をDB上の既存Jobに反映
    properties:
      org.quartz.threadPool.threadCount: 5

initialize-schema: alwaysは開発環境向けの設定で、起動のたびに既存のQRTZ_テーブルを削除して作り直します。本番環境では、Quartz配布物のDDLをFlywayやLiquibaseのマイグレーションで管理するほうが安全です。

@Scheduledとの比較

Springには簡易的な@Scheduledアノテーションもあります。

  • @Scheduled: メソッドにアノテーションを付けるだけで動く。手軽だが、DB永続化やクラスタリング機能はない。
  • Quartz: 設定は少し増えるが、永続化、クラスタリング、詳細な制御が可能。

選択基準としては、サーバー再起動でスケジュールが飛んでも良い軽い処理なら@Scheduled、絶対に実行保証が必要な業務バッチならQuartzを選ぶのが正解です。

Spring Bootを一から学び直したい方には「後悔しないためのSpring Boot 入門書:Spring 解体新書(第2版)」がおすすめです。

QuartzのようなSpring連携機能を扱う前提の基礎知識が身につきます。

気になった方はチェックしてみてください:Amazonで見る(楽天市場 / Yahoo!ショッピングでも購入可能)

Quartzを使うべきケース/使わないべきケース

何でもQuartzを使えば良いというわけではありません。私の判断基準はシンプルです。

「サーバー再起動後もスケジュールが残っている必要があるか?」がYesならQuartz、Noなら@ScheduledかScheduledExecutorで十分です。

Quartzが向いているシステム

  • エンタープライズシステム: 信頼性が最優先される金融、流通、通信などの基幹システム。
  • 複雑なスケジュール: 「第3営業日」など、カレンダーロジックが必要な場合。
  • ジョブの動的追加: 管理画面からユーザーが自由にスケジュールを登録・変更する機能がある場合。

Quartzがオーバースペックになるケース

  • 単純な定期実行: 「10分おきにキャッシュをクリアする」程度なら、ScheduledExecutorや@Scheduledで十分です。
  • マイクロサービス: 各サービスが個別にQuartzを持つと管理が複雑になります。

代替手段(AWS EventBridge等)

クラウド環境、特にAWSを利用しているなら、Amazon EventBridge Schedulerも強力な選択肢です。

サーバーレスでスケジュール管理ができ、サーバーの維持管理コストがかかりません。

バッチ処理自体をAWS Lambdaなどで実装し、キックする役割をEventBridgeに任せる構成は、モダンなアーキテクチャとして人気があります。

インフラに依存せず、アプリケーション内で完結させたい場合にQuartzを採用しましょう。

また、Java専用の軽量な代替としてJobRunrも注目されています。

JobRunr 7以降はJDK 21以上で動かすとワーカーが仮想スレッド(Virtual Threads)になるのが既定で、I/O待ちの多いジョブをさばきやすく、比較的少ない設定で始められる点がメリットです。

Quartz Schedulerに関するよくある質問

Q1. Spring BootでQuartzを使うには?

A1. Spring Boot Starter Quartz(spring-boot-starter-quartz)を依存関係に追加し、JobDetail・Triggerを@Beanとして定義するのが基本パターンです。Spring Boot 3.x・4.xどちらでも同じ手順で、spring.quartz.job-store-typeをmemory(既定)にするとRAMストア、jdbcにするとDB永続化になります。

Q2. ScheduledExecutorとQuartzの違いは?

A2. ScheduledExecutorはシンプルな定期実行に向きますが、アプリ再起動でスケジュールが消え、cron式のような複雑な時刻指定もできません。Quartzはcron式・永続化(JDBC JobStore)・Misfire制御を標準で備え、堅牢なジョブ管理が必要な場面に向いています。

Q3. Quartzのcron式はどう設定しますか?

A3. CronTriggerに秒・分・時・日・月・曜日の6〜7フィールドのcron式(例: "0 0 12 * * ?"で毎日正午実行)を渡します。Unix cronと似ていますが秒フィールドがある点が異なります。

Q4. Quartzを使うべきでないケースはありますか?

A4. 単純な定期実行だけならSpring標準の@Scheduledで十分で、Quartz導入はオーバースペックになりがちです。分散環境でのジョブ管理が主目的ならAWS EventBridge等のマネージドサービスも選択肢になります。

Q5. 永続化(JDBC JobStore)はなぜ必要?

A5. デフォルトのRAMJobStoreはアプリ再起動でスケジュール情報が消えます。JDBC JobStoreを使うとジョブ・トリガー情報をDBに永続化でき、サーバー再起動やクラスタ構成でもスケジュールが失われません。

あわせて読む
あわせて読む

まとめ:Quartzでバッチ処理を簡単設計

今回は、Javaの強力なスケジューラであるQuartzについて解説しました。

結論として、業務システムで確実なスケジュール管理を行うなら、Quartzの導入を強くお勧めします。

理由は、Quartzが以下の3つの重要な課題を解決してくれるからです。

  1. 永続化: サーバー再起動でもスケジュールを守る。
  2. 柔軟性: 複雑なcron式やカレンダー制御に対応できる。
  3. 拡張性: Spring Bootとの連携やクラスタリングが容易。

最初は設定項目が多く感じるかもしれませんが、一度雛形を作ってしまえば、これほど頼りになる相棒はいません。

単純なループ処理での実装は卒業し、Quartzを使って堅牢なシステム構築を目指しましょう。

※この記事の情報は2026年9月時点のものです。Quartzの最新バージョンは公式サイトで確認できます。

まずは手元の開発環境で、最小構成のサンプルコードを動かすところから始めてみてはいかがでしょうか。その小さな一歩が、安定したシステム運用の第一歩になります。

REVISIONS / 改訂履歴
REV.DATE内容
62026-10-16図解を描き直し(図面のデザインにそろえた)
52026-10-14雰囲気だけの挿絵を外した
42026-10-04記載内容の事実確認と修正
32026-09-042026年9月時点の情報で全体を見直し
… ほか1回の改訂
12025-11-22初版
NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Java入門