此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.5spring-doc.cadn.net.cn

任务执行和调度

在没有Executorbean 中,Spring Boot 会自动配置一个AsyncTaskExecutor. 启用虚拟线程后(使用 Java 21+ 和spring.threads.virtual.enabled设置为true),这将是一个SimpleAsyncTaskExecutor使用虚拟线程。 否则,它将是一个ThreadPoolTaskExecutor具有合理的默认值。spring-doc.cadn.net.cn

自动配置的AsyncTaskExecutor用于以下集成,除非自定义Executorbean 定义如下:spring-doc.cadn.net.cn

虽然这种方法在大多数情况下都有效,但 Spring Boot 允许您覆盖自动配置的AsyncTaskExecutor. 默认情况下,当自定义Executorbean 已注册,则自动配置的AsyncTaskExecutorbacks off 和自定义的Executor用于常规任务执行(通过@EnableAsync).spring-doc.cadn.net.cn

但是,Spring MVC、Spring WebFlux 和 Spring GraphQL 都需要一个名为applicationTaskExecutor. 对于 Spring MVC 和 Spring WebFlux,此 bean 的类型必须为AsyncTaskExecutor,而 Spring GraphQL 不强制执行此类型要求。spring-doc.cadn.net.cn

Spring WebSocket 和 JPA 将使用AsyncTaskExecutor如果此类型的单个 Bean 可用,或者名为applicationTaskExecutor已定义。spring-doc.cadn.net.cn

最后,的 boostrap 执行程序ApplicationContext使用名为applicationTaskExecutor除非名为bootstrapExecutor已定义。spring-doc.cadn.net.cn

以下代码片段演示了如何注册自定义AsyncTaskExecutor与 Spring MVC、Spring WebFlux、Spring GraphQL、Spring WebSocket、JPA 和 bean 的后台初始化一起使用。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如果没有@Primarybean 或名为taskExecutor的类型ExecutorAsyncConfigurer存在于应用程序上下文中。spring-doc.cadn.net.cn

如果 auto-configuredAsyncTaskExecutor也不是applicationTaskExecutorbean 定义时,应用程序默认使用名为taskExecutor对于常规任务执行 (@EnableAsync),遵循 Spring Framework 的行为。 但是,此 bean 不会用于 Spring MVC、Spring WebFlux、Spring GraphQL。 但是,如果 bean 的类型是AsyncTaskExecutor.spring-doc.cadn.net.cn

如果您的应用程序需要多个Executor用于不同集成的 bean,例如用于常规任务执行的 bean@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
	}

}

自动配置的ThreadPoolTaskExecutorBuilderSimpleAsyncTaskExecutorBuilder允许您轻松创建类型为AsyncTaskExecutor复制 auto-configuration 的默认行为。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()
	}

}

如果taskExecutornamed bean 不是一个选项,您可以将 bean 标记为@Primary或定义一个AsyncConfigurerbean 来指定Executor负责处理常规任务执行@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()
	}

}

注册自定义Executor同时保持 auto-configuredAsyncTaskExecutor中,您可以创建自定义Executorbean 并设置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()
	}

}

在这种情况下,您将能够自动装配您的自定义Executor添加到其他组件中,同时保留自动配置的AsyncTaskExecutor. 但是,请记住使用@Qualifier注释@Autowired.spring-doc.cadn.net.cn

如果无法做到这一点,则可以请求 Spring Boot 自动配置一个AsyncTaskExecutor总之,如下所示:spring-doc.cadn.net.cn

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

自动配置的AsyncTaskExecutor将自动用于所有集成,即使自定义的ExecutorBean 已注册,包括标记为@Primary. 这些集成包括:spring-doc.cadn.net.cn

根据您的目标排列方式,您可以设置spring.task.execution.modeforce要自动配置applicationTaskExecutor,将Executor转换为AsyncTaskExecutor或定义AsyncTaskExecutor以及一个AsyncConfigurer包装您的自定义Executor.spring-doc.cadn.net.cn

什么时候forcemode 已启用,applicationTaskExecutor还将配置为常规任务执行@EnableAsync,即使@Primarybean 或名为taskExecutor的类型Executor存在。 覆盖Executor对于常规任务,则通过注册AsyncConfigurer豆。spring-doc.cadn.net.cn

ThreadPoolTaskExecutor是自动配置的,则线程池使用 8 个核心线程,这些线程可以根据负载进行扩展和收缩。 这些默认设置可以使用spring.task.executionnamespace 中,如以下示例所示: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.schedulingnamespace 中,如以下示例所示: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

一个ThreadPoolTaskExecutorBuilderbean、一个SimpleAsyncTaskExecutorBuilderbean、一个ThreadPoolTaskSchedulerBuilderbean 和SimpleAsyncTaskSchedulerBuilder在上下文中可用。 这SimpleAsyncTaskExecutorBuilderSimpleAsyncTaskSchedulerBuilder如果启用了 bean,则 bean 会自动配置为使用虚拟线程(使用 Java 21+ 和spring.threads.virtual.enabled设置为true).spring-doc.cadn.net.cn