Spring BootのScheduledは、デフォルトで1つしかスレッドを立ち上げてくれない

こんにちは。 エキサイト株式会社の三浦です。

Spring Bootには「Scheduled」というアノテーションがあり、これを使うことでアプリケーションコード内でバッチ等の定期実行をさせることが出来ます。

今回は、このScheduledを使う際の、スレッド数に関する注意点を説明してきます。

Scheduledとは

以前別の記事で紹介しましたが、Scheduledを使うことでアプリケーションコード内に定期実行を記述できます。

tech.excite.co.jp

Spring Bootでバッチを実行するならぜひ使いたい便利機能ですが、注意点もあります。

Scheduledとスレッド数

例えば以下のようなコードを書く時、どのような挙動を期待するでしょうか?

@Scheduled(timeUnit = TimeUnit.SECONDS, fixedDelay = 1)
public void test1() {
    System.out.println("start test1");

    try {
        Thread.sleep(3000);
    } catch (Exception exception) { }

    System.out.println("end test1");
}

@Scheduled(timeUnit = TimeUnit.SECONDS, fixedDelay = 1)
public void test2() {
    System.out.println("start test2");

    try {
        Thread.sleep(3000);
    } catch (Exception exception) { }

    System.out.println("end test2");
}

おそらくは、以下を想像するでしょう。

start test1
start test2
end test1
end test2
start test1
start test2
...

つまり、 test1test2 が並行で実行される、というものです。

ですが実際は、以下のようになります。

実はScheduledは、デフォルトでは1スレッドでしか動いてくれません。

つまり、Scheduledを付けたメソッドすべてを合わせて、合計1つしか同時に実行してくれないのです。

ですが、並行していろいろなバッチを実行したいという要望は少なからずあるはずです。

では、どうすればよいのでしょうか。

Scheduledを複数スレッドで動かす方法

実は方法は非常にシンプルで、以下の記述を application.yml に書くだけです。

spring:
  task:
    scheduling:
      pool:
        size: 10 // ここに最大並列数を記述

これで、記述した数だけ並行して実行してくれるようになります。

最後に

バッチの同時並行については、開発中にあまり気にすることがないため、出来ないことに気づかずに進んでしまうこともあると思います。

この記事がきっかけになってそれに気づき、解決してもらえれば幸いです。