0


Spring异步注解@Async的使用及其自定义线程池配置总结

正文:
在构建高性能的Spring应用程序时,异步处理是一项关键技术,而Spring通过@Async注解以及相关的线程池配置为我们提供了强大的异步编程支持。本文将深入探讨@Async注解的使用,以及如何借助它在Spring应用中轻松实现非阻塞式异步任务执行。并且将详细探讨如何在Spring中使用AsyncConfigurer接口来指定线程池,以及直接注册线程池Bean这两种方法,并通过实例展示它们在实现不同异步方法时的差异和适用场景。

一、@Async异步注解的使用

1.1 引入异步注解@Async

首先,在使用@Async之前,我们需要确保已经启用了Spring的异步任务执行功能。这通常通过在配置类上添加@EnableAsync注解来完成:

Java1import org.springframework.context.annotation.Configuration;2import org.springframework.scheduling.annotation.EnableAsync;34@Configuration5@EnableAsync6public classAsyncConfiguration{7// 其他配置...

启用该特性后,Spring会创建一个代理来处理那些标记了@Async的方法。

1.2 使用@Async注解

@Async注解可以应用于任何Spring Bean(通常是Service层的方法)的方法声明上,指示该方法应该在一个单独的线程中异步执行:

importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;@ServicepublicclassAsyncService{@AsyncpublicvoidasyncMethod(){// 这个方法将在一个独立的线程中执行// 执行耗时的操作,如数据库查询、网络请求等}}

需要注意的是,被@Async标注的方法必须是void类型的,且不能有返回值,除非返回类型是Future,这样可以通过Future获取异步操作的结果。

1.3 @Async方法的异常处理

由于异步方法是在后台线程中执行的,因此抛出的异常不会立即中断主线程的执行。为了捕获和处理这些异常,可以利用@Async注解所在方法所在的类上的@AsyncExceptionHandler方法:

@ServicepublicclassAsyncService{@AsyncpublicvoidasyncMethod(){// 可能抛出异常的异步代码}@AsyncExceptionHandlerpublicvoidhandleAsyncException(Exception ex){// 处理异步方法中抛出的异常}}

综上所述,Spring的@Async注解极大地简化了异步编程模型,使得开发者能够方便地实现异步任务调度,提高系统并发处理能力和用户体验。同时,合理配置线程池并妥善处理异步任务中可能出现的异常,也是保障系统稳定性和健壮性的重要环节。

二、自定义@Async 注解的线程池

2.1 方法 1 使用AsyncConfigurer指定线程池

AsyncConfigurer接口是Spring框架用于全局配置异步执行器(即线程池)的核心接口。当我们的Spring应用需要统一管理所有异步任务的执行环境时,可以选择实现此接口。

@Configuration@EnableAsyncpublicclassGlobalAsyncConfigimplementsAsyncConfigurer{@OverridepublicExecutorgetAsyncExecutor(){ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);// 核心线程数
        executor.setMaxPoolSize(10);// 最大线程数
        executor.setQueueCapacity(20);// 队列容量
        executor.setThreadNamePrefix("global-");// 线程名称前缀
        executor.initialize();return executor;}}

在此示例中,GlobalAsyncConfig类实现了AsyncConfigurer接口,并在getAsyncExecutor()方法中配置了一个全局的线程池。这意味着,对于应用中所有标记为@Async的方法,默认都会使用这个配置好的线程池执行异步任务。

@ServicepublicclassMyService{@AsyncpublicvoidexecuteGlobalTask(){// 此方法将使用GlobalAsyncConfig中配置的线程池执行}}

2.2 方法 2 指定使用自定义的线程池 Excutor 实例 Bean

在Spring容器中注册一个线程池Bean,这种方式允许你根据业务需求更加灵活地管理和分配不同的线程池资源。

@ConfigurationpublicclassCustomThreadPoolConfig{@Bean(name ="customExecutor")publicThreadPoolTaskExecutorcustomExecutor(){ThreadPoolTaskExecutor executor =newThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(10);
        executor.setThreadNamePrefix("custom-");
        executor.initialize();return executor;}}

现在,我们可以明确地将特定的线程池Bean与某个异步方法关联起来:

@ServicepublicclassMyService{@Async("customExecutor")publicvoidexecuteCustomTask(){// 此方法将使用CustomThreadPoolConfig中名为customExecutor的线程池执行}}

通过在@Async注解中指定"customExecutor",系统将优先使用这个名字注册在Spring容器中的线程池,而不是全局配置的线程池。

2.3 Spring 的默认线程池配置

  1. 注意早期版本的Spring Boot环境中,如果用户没有自定义配置异步执行器(Async Executor),并且没有实现AsyncConfigurer接口来提供一个自定义的执行器,那么Spring Boot会使用一个默认的异步执行器,而在某些早期版本或特定配置下,这个默认执行器可能是SimpleAsyncTaskExecutor,这是个不重用线程、无界并发的执行器。每个提交的任务创建一个新的线程来执行。这意味着每次调用都会创建新的线程资源,而不从固定大小的线程池中获取可用线程。
  2. 在后期版本中,如果没有 Executor 的实例 Spring Boot将会使用其默认配置的线程池(名称为 taskExecutor)来执行被@Async注解修饰的异步方法。
  3. 在Spring Boot如果不存在 Excutor Bean 会通过TaskExecutionAutoConfiguration,它会自动配置一个基于ThreadPoolTaskExecutor的默认线程池,取名为applicationTaskExecutor 和 taskExecutor 进行自动配置。如果已经自定义了Executor bean 那么applicationTaskExecutor将不会自动配置。
  4. 这个默认线程池的相关配置通常基于Spring Boot的默认属性这些属性可以根据应用的具体需求,在application.properties或application.yml文件中进行调整。例如: 1. spring.task.execution.pool.core-size:核心线程数,默认值可能依赖于具体版本,一般较小。2. spring.task.execution.pool.max-size:最大线程数,默认值也可能因版本不同而变化。3. spring.task.execution.pool.queue-capacity:线程池的工作队列容量。4. spring.task.execution.pool.keep-alive:空闲线程的存活时间。
标签: spring java 后端

本文转载自: https://blog.csdn.net/weixin_40979518/article/details/137528616
版权归原作者 栗子叶 所有, 如有侵权,请联系我们删除。

“Spring异步注解@Async的使用及其自定义线程池配置总结”的评论:

还没有评论