SpringBoot 中使用 @Async
使用 @Async 注解步骤:
- 添加 @EnableAsync 注解。在主类上或者 某个类上,否则,异步方法不会生效
- 添加 @Async 注解。在异步方法上添加此注解。异步方法不能被 static 修饰
- 需要自定义线程池,则可以配置线程池
基本使用
在Spring Boot中,您可以使用@Async注解来实现异步方法调用。@Async注解允许您将一个方法标记为异步执行,这意味着方法的调用将立即返回,而不会等待方法的执行完成。
要在Spring Boot应用程序中使用@Async,请按照以下步骤进行操作:
1. 添加依赖:首先,您需要确保您的Spring Boot项目具有适当的依赖项。确保您的pom.xml文件中包含spring-boot-starter-web和spring-boot-starter-aop依赖,因为@Async依赖于AOP(面向切面编程)来实现异步执行。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies>
2.配置异步执行:在Spring Boot应用程序的主类上添加@EnableAsync
注解,以启用异步执行。通常,主类是带有public static void main(String[] args)
方法的类。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
3.创建异步方法:在您的服务类或任何其他组件中,使用@Async
注解标记要异步执行的方法。
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class MyService { @Async public void asyncMethod() { // 异步执行的代码 } }
4.调用异步方法:在需要异步执行的地方调用带有@Async
注解的方法。
@Service public class AnotherService { private final MyService myService; public AnotherService(MyService myService) { this.myService = myService; } public void someMethod() { // 同步代码 // 调用异步方法 myService.asyncMethod(); // 继续执行其他同步代码 } }
现在,当调用myService.asyncMethod()时,该方法将在单独的线程中异步执行,而不会阻塞调用者线程。
请注意,要使@Async正常工作,您还需要配置一个TaskExecutor bean。Spring Boot提供了默认的SimpleAsyncTaskExecutor,但您也可以根据需要配置自定义的执行器。例如,您可以在application.properties或application.yml中添加以下配置:
spring: task: execution: pool: core-size: 5
这个配置示例将创建一个具有5个核心线程的线程池来执行异步方法。您可以根据您的需求进行调整。
希望这可以帮助您在Spring Boot中使用@Async
来实现异步方法调用。
@Async适应自定义线程池
@Async 底层原理:就是通过线程池创建一个线程,然后去执行业务逻辑。
@Async 注解会应用默认线程池 SimpleAsyncTaskExecutor
这种TaskExecutor接口的实现不会复用线程,对应每个请求会新创建一个对应的线程来执行。它支持的并发限制将阻止任何超出限制的调用,这个可以通过调用setConcurrencyLimit方法来限制并发数,默认是不限制并发数的。
@Async 默认异步配置使用的是 SimpleAsyncTaskExecutor,该线程池默认来一个任务创建一个线程,若系统中不断的创建线程,最终会导致系统占用内存过高,引发 OutOfMemoryError 错误。针对线程创建问题,
SimpleAsyncTaskExecutor 提供了限流机制,通过 concurrencyLimit 属性来控制开关,当 concurrencyLimit>=0 时开启限流机制,默认关闭限流机制,即 concurrencyLimit=-1,当关闭情况下,会不断创建新的线程来处理任务。基于默认配置,SimpleAsyncTaskExecutor 并不是严格意义的线程池,达不到线程复用的功能
Spring允许您为异步方法配置不同的TaskExecutor,以便更好地控制异步任务的执行。
以下是如何在Spring Boot中配置自定义线程池并将其用于@Async方法的步骤:
1. 创建一个自定义的TaskExecutor bean,以定义您的线程池配置。您可以在Spring的配置类(通常是带有@Configuration注解的类)中完成此操作。例如:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration public class CustomThreadPoolConfig { @Bean("customTaskExecutor") public TaskExecutor customTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); // 设置核心线程数 executor.setMaxPoolSize(20); // 设置最大线程数 executor.setQueueCapacity(100); // 设置队列容量 executor.setThreadNamePrefix("custom-async-"); // 设置线程名称前缀 executor.initialize(); return executor; } }
上述代码创建了一个名为customTaskExecutor的自定义TaskExecutor bean,您可以根据需要调整线程池的各种参数。
2.在@Async注解中使用自定义的TaskExecutor bean名称。在需要异步执行的方法上,使用@Async注解并指定要使用的TaskExecutor bean的名称,如下所示:
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class MyService { @Async("customTaskExecutor") // 使用自定义的TaskExecutor public void asyncMethod() { // 异步执行的代码 } }
这里,@Async注解中的value属性设置为您在第一步中定义的customTaskExecutor bean的名称。
3. 现在,当调用myService.asyncMethod()时,该方法将在自定义的线程池中异步执行。
这样,您就可以轻松地配置和使用自定义线程池来管理异步任务的执行。这对于需要更多控制的复杂应用程序非常有用。确保根据您的需求调整线程池的大小和其他参数。