让你的 Spring Boot 应用飞起来!@Async 异步编程魔法
这篇文章是用来详细讲解 @Async
注解,它解决的问题,以及使用方法,并提供由易到难的实例,最后用大白话总结,方面各位理解。
一、@Async
是什么?解决了什么问题?
-
@Async
是什么:@Async
是 Spring 框架提供的一个注解,用于将方法标记为异步执行。简单来说,就是让这个方法在另一个线程中执行,而不是在调用它的线程中执行。 -
解决了什么问题:
- 提高响应速度: 当一个方法执行时间较长时,如果同步执行,会导致调用它的线程阻塞,影响程序的响应速度。使用
@Async
可以将这个方法放到另一个线程中执行,让调用线程可以继续执行其他任务,从而提高程序的响应速度。 - 提高并发能力: 当需要同时执行多个耗时任务时,可以使用
@Async
将这些任务放到不同的线程中执行,从而提高程序的并发能力。 - 避免阻塞主线程: 在 Web 应用中,如果某个请求处理需要执行耗时操作,可以使用
@Async
将这个操作放到另一个线程中执行,避免阻塞主线程,从而提高 Web 应用的吞吐量。
- 提高响应速度: 当一个方法执行时间较长时,如果同步执行,会导致调用它的线程阻塞,影响程序的响应速度。使用
二、@Async
的使用方法
-
开启异步支持: 在 Spring Boot 应用的主类上添加
@EnableAsync
注解,开启异步支持。 -
标记异步方法: 在需要异步执行的方法上添加
@Async
注解。
三、@Async
实例 (由易到难)
1. 简单示例:异步发送邮件
-
需求: 用户注册成功后,异步发送一封欢迎邮件。
-
步骤:
-
创建 Spring Boot 应用:
- 使用 Spring Initializr 创建一个 Spring Boot 应用。
- 添加
spring-boot-starter-web
依赖。
-
开启异步支持:
-
在
MyApplication.java
(或者你的主类) 中添加@EnableAsync
注解:import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync // 开启异步支持 public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
-
-
创建邮件发送服务:
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class EmailService { @Async // 标记为异步方法 public void sendWelcomeEmail(String email) { // 模拟发送邮件,耗时 5 秒 System.out.println("Sending welcome email to " + email + "..."); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Welcome email sent to " + email); } }
- 解释:
@Async
:将sendWelcomeEmail()
方法标记为异步方法。Thread.sleep(5000)
:模拟发送邮件的耗时操作。
- 解释:
-
创建用户注册服务:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private EmailService emailService; public void registerUser(String email) { // 模拟用户注册 System.out.println("Registering user with email: " + email); // 异步发送欢迎邮件 emailService.sendWelcomeEmail(email); System.out.println("User registered successfully."); } }
- 解释:
emailService.sendWelcomeEmail(email)
:调用EmailService
的sendWelcomeEmail()
方法发送邮件。
- 解释:
-
创建 Controller:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/register") public String register(@RequestParam("email") String email) { userService.registerUser(email); return "User registration initiated. Check console for async email sending."; } }
-
运行应用:
- 运行
MyApplication
类。
- 运行
-
测试 API:
-
在浏览器或使用 curl 命令访问以下 URL:
http://localhost:8080/register?email=test@example.com
-
你应该会看到 "User registration initiated." 的响应,并且在控制台中会看到异步发送邮件的日志。
-
-
-
代码: (完整代码)
// MyApplication.java package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication @EnableAsync public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } // EmailService.java package com.example; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class EmailService { @Async public void sendWelcomeEmail(String email) { System.out.println("Sending welcome email to " + email + "..."); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Welcome email sent to " + email); } } // UserService.java package com.example; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private EmailService emailService; public void registerUser(String email) { System.out.println("Registering user with email: " + email); emailService.sendWelcomeEmail(email); System.out.println("User registered successfully."); } } // UserController.java package com.example; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @Autowired private UserService userService; @GetMapping("/register") public String register(@RequestParam("email") String email) { userService.registerUser(email); return "User registration initiated. Check console for async email sending."; } }
2. 中级示例:自定义线程池
-
需求: 使用自定义的线程池来执行异步任务。
-
步骤:
-
创建线程池配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") // 指定线程池的名称 public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); // 核心线程数 executor.setMaxPoolSize(10); // 最大线程数 executor.setQueueCapacity(25); // 队列容量 executor.setThreadNamePrefix("MyAsyncThread-"); // 线程名称前缀 executor.initialize(); return executor; } }
- 解释:
@Configuration
:将AsyncConfig
类标记为一个配置类。@EnableAsync
:开启异步支持。@Bean(name = "taskExecutor")
:创建一个名为taskExecutor
的 Bean,类型为Executor
。ThreadPoolTaskExecutor
:Spring 提供的线程池实现。setCorePoolSize()
:设置核心线程数。setMaxPoolSize()
:设置最大线程数。setQueueCapacity()
:设置队列容量。setThreadNamePrefix()
:设置线程名称前缀。
- 解释:
-
指定使用的线程池:
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class EmailService { @Async("taskExecutor") // 指定使用的线程池名称 public void sendWelcomeEmail(String email) { System.out.println("Sending welcome email to " + email + "..."); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Welcome email sent to " + email); } }
- 解释:
@Async("taskExecutor")
:指定使用名为taskExecutor
的线程池来执行sendWelcomeEmail()
方法。
- 解释:
-
3. 高级示例:异步任务的异常处理
-
需求: 捕获异步任务中发生的异常,并进行处理。
-
步骤:
-
实现
AsyncConfigurer
接口:import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import java.lang.reflect.Method; import java.util.concurrent.Executor; @Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { // 可以自定义线程池 return null; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new MyAsyncExceptionHandler(); } }
- 解释:
AsyncConfigurer
:Spring 提供的接口,用于配置异步任务。getAsyncExecutor()
:可以自定义线程池。getAsyncUncaughtExceptionHandler()
:用于指定异步任务的异常处理器。
- 解释:
-
创建异常处理器:
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import java.lang.reflect.Method; public class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler { @Override public void handleUncaughtException(Throwable ex, Method method, Object... params) { System.err.println("Async method has uncaught exception:"); System.err.println("Method: " + method.getName()); System.err.println("Exception message: " + ex.getMessage()); } }
- 解释:
AsyncUncaughtExceptionHandler
:Spring 提供的接口,用于处理异步任务中发生的未捕获异常。handleUncaughtException()
:处理异常的方法。
- 解释:
-
四、大白话总结
@Async
: 就像请了一个 "临时工",帮你干一些比较慢的活,这样你就不用一直等着,可以先去干其他的事情。@EnableAsync
: 告诉 Spring "我要用临时工了!"- 线程池: 就像一个 "临时工管理中心",可以管理多个 "临时工",让他们更有效率地工作。
- 异常处理: 就像给 "临时工" 买了保险,万一他们出了什么问题,也能及时处理。
更简洁的总结:
@Async
让方法异步执行,就像请了个临时工。@EnableAsync
开启异步支持,告诉 Spring 可以用临时工了。- 可以自定义线程池,管理临时工。
- 可以进行异常处理,给临时工买保险。
希望这篇文章能够帮助你理解 @Async
注解!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~