概要
Springが提供している @Scheduledについて調べたので、そのメモを残す。
下記のversionで検証を行った。
- Java17(Corretto 17.0.5)
- SpringBoot2.7.5
検証コードは下記に格納している。
https://github.com/nannany/spring-scheduled
@Scheduled
とは?
@Scheduled
アノテーションをメソッドに付与することで、メソッドの定期的な実行を行うことができる。
例えば、下記のようなメソッドはfixedRate_withTimeUnit
という文言を1分ごとに標準出力する。
@Scheduled(fixedRate = 1, timeUnit = TimeUnit.MINUTES)
public void fixedRate_withTimeUnit() {
logger.info("fixedRate_withTimeUnit");
}
@Scheduled
を有効にするには?
@Scheduled
を有効にするには、下記のように@Configuration
が付与されたクラスに、@EnableScheduling
を付与してやれば良い。(参考)
@Configuration
@EnableScheduling
@ComponentScan(basePackages = "com.example.demo.tasks")
public class EnableSchedulingConfig implements SchedulingConfigurer {
...
@Scheduled
の機能
@Scheduled
でメソッドの定期的な実行を行うことができるが、実行タイミングの指定方法は複数ある。
fixedRate
fixRate
を用いた指定方法では、シンプルな定期実行が可能である。
下記のメソッドのように指定した場合、5秒ごとに fixedRate
という文言がログに吐き出される。
@Scheduled(fixedRate = 5000)
public void fixedRate() throws InterruptedException {
Thread.sleep(1000);
logger.info("fixedRate");
}
fixedRateで指定する値はデフォルトでミリ秒であるが、timeUnitによって指定することが可能である。
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.SECONDS)
public void fixedRate_withTimeUnit() {
logger.info("fixedRate_withTimeUnit");
}
fixedDelay
fixedDelay
では、該当のメソッドが終了してから指定した時間経った後に再度メソッドが実行される。
例えば、下記の場合だと6秒ごとに fixedDelay
という文言が出力される。
途中でsleepしているため、メソッドの実行には1秒かかり、その完了の後の5秒後にメソッドが再度実行されるため、6秒ごとのログ出力となる。
@Scheduled(fixedDelay = 5000)
public void fixedDelay() throws InterruptedException {
Thread.sleep(1000);
logger.info("fixedDelay");
}
cron
cron
ではいわゆるcron式による定義が可能となる。
下記の例だと、5秒ごとに cron
をログ出力する。ちなみにタイムゾーンの指定も可能である。(下記の例だと意味をなしていないが)
@Scheduled(cron = "*/5 * * * * *", zone = "Asia/Tokyo")
public void cron() {
logger.info("cron");
}
ランタイムで次回実行を決めたいとき
@Scheduled
ではアプリケーションコンテキスト生成時に実行間隔が決定するため、ランタイム時に次回実行を決定したい時には ScheduledTaskRegistrar
をいじってやる必要がある。
下記の例だと、 cumstom scheduler
という文言が 1~5秒ごとにログ出力されるようになる。
@Bean
public Executor taskExecutor() {
return Executors.newSingleThreadScheduledExecutor();
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
taskRegistrar.addTriggerTask(
() -> logger.info("custom scheduler"),
triggerContext -> {
Random random = new Random();
Date date = new Date();
return Date.from(date.toInstant().plusSeconds(random.nextInt(5) + 1));
}
);
}
参考
https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#scheduling
https://www.baeldung.com/spring-scheduled-tasks