在 Spring Boot 中,@Async
注解用于实现异步方法调用,允许方法在单独的线程中执行,从而避免阻塞主线程,提升应用的并发处理能力。
1. 基本用法
在 Spring Boot 中使用 @Async
很简单,主要步骤如下:
步骤 1:启用异步支持
首先,需要在 Spring Boot 应用程序的启动类或配置类上加上 @EnableAsync
注解,以启用异步方法的支持。
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
步骤 2:定义异步方法
然后,在需要异步执行的方法上加上 @Async
注解。注意,异步方法需要返回 void
或 Future
类型(如 CompletableFuture
)。
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncService {
@Async
public void asyncMethod() {
// 模拟耗时操作
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步方法执行完成");
}
@Async
public CompletableFuture<String> asyncMethodWithReturn() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture("异步方法带返回值执行完成");
}
}
步骤 3:调用异步方法
当调用 @Async
注解的方法时,方法将会在独立的线程中执行,不会阻塞调用它的线程。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@RestController
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("/async")
public String callAsyncMethod() {
asyncService.asyncMethod();
return "调用了异步方法";
}
@GetMapping("/async-with-return")
public CompletableFuture<String> callAsyncMethodWithReturn() {
return asyncService.asyncMethodWithReturn();
}
}
2. 自定义线程池
默认情况下,Spring 使用 SimpleAsyncTaskExecutor
来处理异步任务,但你可以自定义线程池来管理这些任务。
自定义线程池配置
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 = "asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("AsyncThread-");
executor.initialize();
return executor;
}
}
然后,在异步方法上指定使用这个线程池:
@Async("asyncExecutor")
public void asyncMethod() {
// 方法实现
}
3. 异步方法的限制
- 异步方法不能是
private
方法,因为 Spring 需要通过代理对象来处理异步调用。 - 异步方法必须通过代理对象调用,不能直接在同一个类内部调用,否则
@Async
不会生效。
4. 异步方法异常处理
对于返回 Future
或 CompletableFuture
的异步方法,可以通过 .exceptionally()
或 .handle()
方法处理异常:
@Async
public CompletableFuture<String> asyncMethodWithException() {
return CompletableFuture.supplyAsync(() -> {
if (true) {
throw new RuntimeException("异常发生");
}
return "成功";
}).exceptionally(ex -> "处理异常: " + ex.getMessage());
}
对于 void
类型的异步方法,可以使用 AsyncUncaughtExceptionHandler
处理未捕获的异常:
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import java.lang.reflect.Method;
@Configuration
public class AsyncExceptionHandler implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println("异步方法出现未捕获异常: " + ex.getMessage());
}
};
}
}
总结
@Async
注解为 Spring Boot 提供了非常简洁的异步调用支持,能有效提升应用的并发处理能力。通过自定义线程池和异常处理机制,还可以更好地控制异步任务的执行与监控。