典型用法
⚠️ 注意:@Async 方法不能是 private,也不能在同一个类中直接调用,否则代理失效。
基础用法:异步发送邮件
在配置类上添加 @EnableAsync 来启用异步功能,方法被 @Async 标记后,Spring 会自动将其放入线程池中异步执行。
java
// 启用异步支持(必须配置)
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
}
--------------------------------------------------------------
// 异步发送邮件
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class EmailService {
@Async
public void sendEmail(String to, String content) {
// 模拟耗时操作
System.out.println("正在异步发送邮件给:" + to);
try {
Thread.sleep(1000); // 模拟发送耗时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
自定义线程池(推荐做法)
默认使用的是 Spring 的简单线程池,建议自定义以提高性能和可控性。
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class CustomAsyncConfig {
@Bean(name = "emailTaskExecutor")
public Executor emailTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Email-Async-");
executor.initialize();
return executor;
}
}
然后在服务中指定使用该线程池:
java
@Async("emailTaskExecutor")
public void sendEmail(String to, String content) {
// 发送逻辑
}
异常处理(推荐封装)
异步方法中的异常不会直接抛出到主线程,需手动捕获或使用 try-catch 处理,也可以结合 @ControllerAdvice 或日志框架统一处理。
java
@Async
public void doSomething() {
try {
// 执行任务
} catch (Exception e) {
// 记录日志或上报监控
System.err.println("异步任务发生异常:" + e.getMessage());
}
}
返回值类型支持
java
// void 类型(无返回值)
@Async
public void logAccess(String user) {
// 记录用户访问日志
}
// Future / CompletableFuture(有返回值)
@Async
public Future<String> fetchData() {
String result = "数据加载完成";
return new AsyncResult<>(result);
}