任务执行与调度

在缺乏执行者在上下文中,Spring Boot 自动配置异步任务执行器. 当虚拟线程启用(使用 Java 21+ 和spring.threads.virtual.enabled设置为true)这将是SimpleAsyncTaskExecutor它使用虚拟线程。 否则,它将是线程池任务执行者而且是合理的默认值。spring-doc.cadn.net.cn

自动配置异步任务执行器除非有自定义功能,否则用于以下集成执行者豆子的定义如下:spring-doc.cadn.net.cn

虽然这种方法在大多数情况下有效,但 Spring Boot 允许你覆盖自动配置异步任务执行器. 默认情况下,当自定义时执行者BEAN 已注册,自动配置异步任务执行器退让,习惯执行者用于常规任务执行(通过@EnableAsync).spring-doc.cadn.net.cn

然而,Spring MVC、Spring WebFlux 和 Spring GraphQL 都要求一个名为applicationTaskExecutor. 对于春季MVC和春季WebFlux,这种豆子必须是类型异步任务执行器而 Spring GraphQL 不强制执行这种类型要求。spring-doc.cadn.net.cn

Spring WebSocket 和 JPA 将使用异步任务执行器如果有单颗此类豆子或有名字的豆子applicationTaskExecutor定义了。spring-doc.cadn.net.cn

最后,boostrap执行者应用上下文使用一种名为applicationTaskExecutor除非有个叫bootstrap执行器定义了。spring-doc.cadn.net.cn

以下代码片段演示如何注册自定义异步任务执行器可与 Spring MVC、Spring WebFlux、Spring GraphQL、Spring WebSocket、JPA 以及豆子的后台初始化一起使用。spring-doc.cadn.net.cn

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-")
	}

}

applicationTaskExecutor如果没有 ,BEAN 也将用于常规任务执行@Primary豆子或豆子,或者叫做任务执行者类型执行者异步配置器在应用上下文中存在。spring-doc.cadn.net.cn

如果都没有,自动配置异步任务执行器也没有applicationTaskExecutorBEAN 被定义后,应用程序默认使用 名为任务执行者对于常规任务执行(@EnableAsync),遵循Spring Framework的行为。 不过,这个 bean 不会用于 Spring MVC、Spring WebFlux、Spring GraphQL。 不过,如果豆子类型为异步任务执行器.spring-doc.cadn.net.cn

如果你的应用需要多个执行者用于不同集成的豆子,例如用于常规任务执行的豆子,以及@EnableAsync以及其他针对 Spring MVC、Spring WebFlux、Spring WebSocket 和 JPA,你可以按以下方式配置。spring-doc.cadn.net.cn

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
	}

}

自动配置线程池任务执行器构建器SimpleAsyncTaskExecutorBuilder允许你轻松创建 类型的实例异步任务执行器它会模拟自动配置的默认行为。spring-doc.cadn.net.cn

import org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder;
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
	SimpleAsyncTaskExecutor taskExecutor(SimpleAsyncTaskExecutorBuilder builder) {
		return builder.build();
	}

}
import org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.SimpleAsyncTaskExecutor

@Configuration(proxyBeanMethods = false)
class MyTaskExecutorConfiguration {

	@Bean
	fun taskExecutor(builder: SimpleAsyncTaskExecutorBuilder): SimpleAsyncTaskExecutor {
		return builder.build()
	}

}

如果任务执行者命名豆不是选项,你可以标记你的豆子为@Primary或定义一个异步配置器豆子来指定执行者负责处理常规任务执行,以下@EnableAsync. 以下示例展示了如何实现这一点。spring-doc.cadn.net.cn

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()
	}

}

注册自定义执行者同时保持自动配置异步任务执行器你可以自定义执行者豆子并设置defaultCandidate=false属性@Bean注释,如下例所示:spring-doc.cadn.net.cn

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()
	}

}

那样的话,你就可以自动接线你的自定义执行者在保留自动配置的同时,进入其他组件异步任务执行器. 不过,记得要使用@Qualifier注释并列@Autowired.spring-doc.cadn.net.cn

如果无法实现,你可以请求 Spring Boot 自动配置异步任务执行器总之,内容如下:spring-doc.cadn.net.cn

spring.task.execution.mode=force
spring:
  task:
    execution:
      mode: force

自动配置异步任务执行器所有集成都会自动使用,即使是自定义的执行者BEAN已注册,包括标记为@Primary. 这些集成包括:spring-doc.cadn.net.cn

根据你的目标安排,你可以设置spring.task.execution.mode以自动配置applicationTaskExecutor,改变你的执行者变成了异步任务执行器或者定义两个异步任务执行器以及异步配置器包装你的定制执行者.spring-doc.cadn.net.cn

什么时候模式已启用,applicationTaskExecutor还将配置为常规任务执行,且@EnableAsync,即使@Primary豆子或豆子,或者叫做任务执行者类型执行者存在。 唯一能覆盖执行者对于常规任务,通过注册一个异步配置器豆。spring-doc.cadn.net.cn

线程池任务执行者是自动配置的,线程池使用8个核心线程,线程可以根据负载变化增长和缩小。 这些默认设置可以通过spring.task.execution命名空间,如下例所示:spring-doc.cadn.net.cn

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秒)。spring-doc.cadn.net.cn

如果调度器需要与计划任务执行关联,也可以自动配置(使用@EnableScheduling例如)。spring-doc.cadn.net.cn

如果启用了虚拟线程(使用 Java 21+ 和spring.threads.virtual.enabled设置为true)这将是SimpleAsyncTaskScheduler它使用虚拟线程。 这SimpleAsyncTaskScheduler会忽略任何与池化有关的房产。spring-doc.cadn.net.cn

如果没有启用虚拟线程,它将成为ThreadPoolTaskScheduler而且是合理的默认值。 这ThreadPoolTaskScheduler默认使用一个线程,其设置可以通过spring.task.scheduleling命名空间,如下例所示:spring-doc.cadn.net.cn

spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
spring:
  task:
    scheduling:
      thread-name-prefix: "scheduling-"
      pool:
        size: 2

一个线程池任务执行器构建器豆,ASimpleAsyncTaskExecutorBuilder豆,AThreadPoolTaskSchedulerBuilder豆子和SimpleAsyncTaskSchedulerBuilder如果需要创建自定义执行器或调度器,则可在上下文中使用。 这SimpleAsyncTaskExecutorBuilderSimpleAsyncTaskSchedulerBuilder如果启用了虚拟线程(使用 Java 21+ 和spring.threads.virtual.enabled设置为true).spring-doc.cadn.net.cn