@Scheduledで同時実行する

Spring Bootではメソッドに@Scheduledをつけると簡単にタスク処理を書くことができます。
ところがこのタスクは複数のメソッドにつけるとお互い排他で動作するようです。

[広告]
[広告]

まずは排他動作を確認

・sample.app.product.ProductTask.groovyを作成
package sample.app.product

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

@Component
class ProductTask {
    private static final Logger log = LoggerFactory.getLogger(this)

    @Scheduled(initialDelay=3000L, fixedDelay=1000L)
    void execute1() {
        log.info("execute1 start")
        sleep(10 * 1000)    // 10秒スリープ
        log.info("execute1 end")
    }

    @Scheduled(initialDelay=3000L, fixedDelay=1000L)
    void execute2() {
        log.info("execute2 start")
        sleep(1 * 1000)    // 1秒スリープ
        log.info("execute2 end")
    }
}
・initialDelayはspring boot起動後に最初に実行するまでの時間(ミリ秒)を指定
・fixedDelayはtask終了後に起動する時間(ミリ秒)を指定
・ほかにもcron指定などできるので、「Spring Bootでtaskを定期実行する方法」の記事などを参考にしてください
・ちなみにこういった値は設定値に書きたくなるのが世の常ですなので、application.propertiesに書くこともできます
 @Scheduled(initialDelayString="\${foo}", fixedDelayString="\${bar}")
 groovyだとJavaとことなりエスケープがいるので注意が必要ですね!

・実行結果
2017-10-14 15:56:44.285  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute2 start
2017-10-14 15:56:45.285  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute2 end
2017-10-14 15:56:45.286  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute1 start
2017-10-14 15:56:55.287  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute1 end
2017-10-14 15:56:55.288  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute2 start
2017-10-14 15:56:56.291  INFO 10244 --- [pool-2-thread-1] sample.app.product.ProductTask           : execute2 end
・execute1が実行中の10秒間は、execute2が実行できてないですね
・これでは困ることがあるので、同時実行できるように修正します

@Scheduledを同時実行できるように設定

・sample.app.common.AppConfig.groovyを作成
package monitor.app.common

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler

@Configuration
class AppConfig {

    @Bean(destroyMethod = "shutdown")
    ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler()
        taskScheduler.poolSize = 10
        return taskScheduler
    }
}
・実行結果
2017-10-14 16:35:33.714  INFO 9792 --- [taskScheduler-1] sample.app.product.ProductTask           : execute1 start
2017-10-14 16:35:33.714  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 start
2017-10-14 16:35:34.733  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 end
2017-10-14 16:35:35.735  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 start
2017-10-14 16:35:36.736  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 end
2017-10-14 16:35:37.738  INFO 9792 --- [taskScheduler-3] sample.app.product.ProductTask           : execute2 start
2017-10-14 16:35:38.739  INFO 9792 --- [taskScheduler-3] sample.app.product.ProductTask           : execute2 end
2017-10-14 16:35:39.741  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 start
2017-10-14 16:35:40.742  INFO 9792 --- [taskScheduler-2] sample.app.product.ProductTask           : execute2 end
2017-10-14 16:35:41.744  INFO 9792 --- [taskScheduler-4] sample.app.product.ProductTask           : execute2 start
2017-10-14 16:35:42.755  INFO 9792 --- [taskScheduler-4] sample.app.product.ProductTask           : execute2 end
2017-10-14 16:35:43.731  INFO 9792 --- [taskScheduler-1] sample.app.product.ProductTask           : execute1 end
・無事にexecute1が実行中もexecute2が別スレッドで実行できていますね!

コメントを残す

メールアドレスが公開されることはありません。