タスクの実行とスケジューリング
コンテキスト内に Executor
(標準 Javadoc) Bean がない場合、Spring Boot は AsyncTaskExecutor
(Javadoc) を自動構成します。仮想スレッドが有効になっている場合 ( Java 21+ を使用し、spring.threads.virtual.enabled
を true
に設定)、これは仮想スレッドを使用する SimpleAsyncTaskExecutor
(Javadoc) になります。それ以外の場合は、適切なデフォルトを持つ ThreadPoolTaskExecutor
(Javadoc) になります。
カスタム Executor
(標準 Javadoc) Bean が定義されていない限り、自動構成された AsyncTaskExecutor
(Javadoc) は次の統合に使用されます。
AsyncConfigurer
(Javadoc) 型の Bean が定義されていない限り、@EnableAsync
(Javadoc) を使用して非同期タスクを実行します。Spring for GraphQL のコントローラーメソッドからの
Callable
(標準 Javadoc) 戻り値の非同期処理。Spring MVC での非同期リクエスト処理。
Spring、WebFlux でのブロック実行のサポート。
Spring、WebSocket の受信および送信メッセージチャネルに使用されます。
JPA リポジトリのブートストラップモードに基づいた、JPA 用のブートストラップエグゼキュータ。
ApplicationContext
内の Bean のバックグラウンド初期化用のブートストラップエグゼキュータ。
このアプローチはほとんどのシナリオで機能しますが、Spring Boot を使用すると自動構成された AsyncTaskExecutor
(Javadoc) をオーバーライドできます。デフォルトでは、カスタム Executor
(標準 Javadoc) Bean が登録されると、自動構成された AsyncTaskExecutor
(Javadoc) はバックオフされ、カスタム Executor
(標準 Javadoc) が通常のタスク実行(@EnableAsync
(Javadoc) 経由)に使用されます。
ただし、Spring MVC、Spring、WebFlux、Spring GraphQL はすべて、applicationTaskExecutor
という名前の Bean を必要とします。Spring MVC および Spring、WebFlux の場合、この Bean は AsyncTaskExecutor
(Javadoc) 型である必要がありますが、Spring GraphQL ではこの型要件は強制されません。
Spring、WebSocket、JPA は、この型の Bean が 1 つだけ使用可能であるか、applicationTaskExecutor
という名前の Bean が定義されている場合、AsyncTaskExecutor
(Javadoc) を使用します。
最後に、ApplicationContext
のブートストラップエグゼキュータは、bootstrapExecutor
という名前の Bean が定義されていない限り、applicationTaskExecutor
という名前の Bean を使用します。
次のコードスニペットは、Spring MVC、Spring、WebFlux、Spring GraphQL、Spring、WebSocket、JPA、Bean のバックグラウンド初期化で使用するカスタム AsyncTaskExecutor
(Javadoc) を登録する方法を示しています。
Java
Kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
SimpleAsyncTaskExecutor applicationTaskExecutor() {
return new SimpleAsyncTaskExecutor("app-");
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.SimpleAsyncTaskExecutor
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
fun applicationTaskExecutor(): SimpleAsyncTaskExecutor {
return SimpleAsyncTaskExecutor("app-")
}
}
アプリケーションコンテキストに |
自動構成された |
アプリケーションで、異なる統合用に複数の Executor
Bean (1 つは @EnableAsync
(Javadoc) を使用した通常のタスク実行用、もう 1 つは Spring MVC、Spring、WebFlux、Spring、WebSocket、JPA 用) が必要な場合は、次のように構成できます。
Java
Kotlin
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
SimpleAsyncTaskExecutor applicationTaskExecutor() {
return new SimpleAsyncTaskExecutor("app-");
}
@Bean("taskExecutor")
ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("async-");
return threadPoolTaskExecutor;
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.SimpleAsyncTaskExecutor
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean("applicationTaskExecutor")
fun applicationTaskExecutor(): SimpleAsyncTaskExecutor {
return SimpleAsyncTaskExecutor("app-")
}
@Bean("taskExecutor")
fun taskExecutor(): ThreadPoolTaskExecutor {
val threadPoolTaskExecutor = ThreadPoolTaskExecutor()
threadPoolTaskExecutor.setThreadNamePrefix("async-")
return threadPoolTaskExecutor
}
}
自動構成された
|
Bean という名前の taskExecutor
が選択できない場合は、Bean を @Primary
(Javadoc) としてマークするか、AsyncConfigurer
(Javadoc) の Bean を定義して、通常のタスク実行を @EnableAsync
(Javadoc) で処理する Executor
を指定します。次の例は、これを実現する方法を示しています。
Java
Kotlin
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean
AsyncConfigurer asyncConfigurer(ExecutorService executorService) {
return new AsyncConfigurer() {
@Override
public Executor getAsyncExecutor() {
return executorService;
}
};
}
@Bean
ExecutorService executorService() {
return Executors.newCachedThreadPool();
}
}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.AsyncConfigurer
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean
fun asyncConfigurer(executorService: ExecutorService): AsyncConfigurer {
return object : AsyncConfigurer {
override fun getAsyncExecutor(): Executor {
return executorService
}
}
}
@Bean
fun executorService(): ExecutorService {
return Executors.newCachedThreadPool()
}
}
自動構成された AsyncTaskExecutor
(Javadoc) を維持しながらカスタム Executor
(標準 Javadoc) を登録するには、次の例に示すように、カスタム Executor
(標準 Javadoc) Bean を作成し、その @Bean
(Javadoc) アノテーションに defaultCandidate=false
属性を設定します。
Java
Kotlin
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyTaskExecutorConfiguration {
@Bean(defaultCandidate = false)
@Qualifier("scheduledExecutorService")
ScheduledExecutorService scheduledExecutorService() {
return Executors.newSingleThreadScheduledExecutor();
}
}
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {
@Bean(defaultCandidate = false)
@Qualifier("scheduledExecutorService")
fun scheduledExecutorService(): ScheduledExecutorService {
return Executors.newSingleThreadScheduledExecutor()
}
}
この場合、自動構成された AsyncTaskExecutor
(Javadoc) を維持しながら、カスタム Executor
(標準 Javadoc) を他のコンポーネントにオートワイヤーできます。ただし、@Autowired
(Javadoc) と併せて @Qualifier
(Javadoc) アノテーションを使用することを忘れないでください。
これが不可能な場合は、次のようにして、Spring Boot に AsyncTaskExecutor
(Javadoc) を自動構成するようにリクエストできます。
プロパティ
YAML
spring.task.execution.mode=force
spring:
task:
execution:
mode: force
自動構成された AsyncTaskExecutor
(Javadoc) は、カスタム Executor
(標準 Javadoc) Bean が登録されている場合でも、すべての統合(@Primary
(Javadoc) としてマークされているものを含む)で自動的に使用されます。これらの統合には以下が含まれます。
AsyncConfigurer
(Javadoc) Bean が存在しない場合は、非同期タスク実行 (@EnableAsync
(Javadoc) )。Spring for GraphQL はコントローラーメソッドからの
Callable
(標準 Javadoc) 戻り値を非同期的に処理します。Spring MVC の非同期リクエスト処理。
Spring、WebFlux のブロッキング実行サポート。
Spring、WebSocket の受信および送信メッセージチャネルに使用されます。
JPA リポジトリのブートストラップモードに基づいた、JPA 用のブートストラップエグゼキュータ。
bootstrapExecutor
という名前の Bean が定義されていない限り、ApplicationContext
内の Bean のバックグラウンド初期化用のブートストラップエグゼキュータ。
ターゲットの配置に応じて、 |
|
ThreadPoolTaskExecutor
(Javadoc) が自動構成されると、スレッドプールは負荷に応じて拡大および縮小できる 8 つのコアスレッドを使用します。これらのデフォルト設定は、次の例に示すように、spring.task.execution
名前空間を使用して微調整できます。
プロパティ
YAML
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
spring:
task:
execution:
pool:
max-size: 16
queue-capacity: 100
keep-alive: "10s"
これにより、キューがいっぱい(100 タスク)になったときにスレッドプールが最大 16 スレッドに増加するように、スレッドプールが制限キューを使用するように変更されます。プールの縮小は、スレッドが 10 秒間(デフォルトでは 60 秒ではなく)アイドル状態のときに回収されるため、より積極的です。
スケジュールされたタスクの実行に関連付ける必要がある場合 (たとえば、@EnableScheduling
(Javadoc) を使用)、スケジューラを自動構成することもできます。
仮想スレッドが有効になっている場合 (Java 21+ を使用し、spring.threads.virtual.enabled
を true
に設定)、これは仮想スレッドを使用する SimpleAsyncTaskScheduler
(Javadoc) になります。この SimpleAsyncTaskScheduler
(Javadoc) は、プール関連のプロパティをすべて無視します。
仮想スレッドが有効になっていない場合は、適切なデフォルトが設定された ThreadPoolTaskScheduler
(Javadoc) になります。ThreadPoolTaskScheduler
(Javadoc) はデフォルトで 1 つのスレッドを使用し、次の例に示すように、spring.task.scheduling
名前空間を使用して設定を微調整できます。
プロパティ
YAML
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
spring:
task:
scheduling:
thread-name-prefix: "scheduling-"
pool:
size: 2
カスタムエグゼキュータまたはスケジューラを作成する必要がある場合、コンテキストで ThreadPoolTaskExecutorBuilder
(Javadoc) Bean、SimpleAsyncTaskExecutorBuilder
(Javadoc) Bean、ThreadPoolTaskSchedulerBuilder
(Javadoc) Bean、SimpleAsyncTaskSchedulerBuilder
(Javadoc) が使用可能になります。SimpleAsyncTaskExecutorBuilder
(Javadoc) および SimpleAsyncTaskSchedulerBuilder
(Javadoc) Bean は、仮想スレッドが有効になっている場合 (Java 21+ および spring.threads.virtual.enabled
を true
に設定して使用)、仮想スレッドを使用するように自動的に構成されます。