本文目录导读:

我来详细介绍Java中如何使用注解实现异步处理,主要基于Spring框架的@Async注解。
基础配置
启用异步支持
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync // 启用异步支持
public class AsyncConfig {
// 可以自定义线程池
}
自定义线程池配置(推荐)
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;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数
executor.setCorePoolSize(5);
// 最大线程数
executor.setMaxPoolSize(10);
// 队列容量
executor.setQueueCapacity(100);
// 线程名前缀
executor.setThreadNamePrefix("async-task-");
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务完成再关闭
executor.setWaitForTasksToCompleteOnShutdown(true);
// 等待时间
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
异步服务示例
简单异步方法
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async // 标记为异步方法
public void sendEmail(String email) {
System.out.println("发送邮件开始: " + Thread.currentThread().getName());
try {
// 模拟耗时操作
Thread.sleep(3000);
System.out.println("发送邮件给: " + email);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发送邮件结束");
}
@Async("taskExecutor") // 指定线程池
public void processOrder(Long orderId) {
System.out.println("处理订单: " + orderId + " - " + Thread.currentThread().getName());
// 处理订单逻辑
}
}
带返回值的异步方法
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
@Service
public class AsyncResultService {
// 返回Future对象
@Async
public Future<String> processData(String data) {
System.out.println("处理数据开始: " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
String result = "处理结果: " + data.toUpperCase();
return new AsyncResult<>(result);
} catch (InterruptedException e) {
return new AsyncResult<>("处理失败");
}
}
// 返回CompletableFuture (推荐)
@Async
public CompletableFuture<User> findUser(Long userId) {
System.out.println("查询用户: " + Thread.currentThread().getName());
// 模拟查询
User user = new User(userId, "User" + userId);
return CompletableFuture.completedFuture(user);
}
// 多个异步调用的组合
@Async
public CompletableFuture<String> combineResults() {
// 模拟组合多个结果
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "组合结果";
});
}
}
// 用户实体类
class User {
private Long id;
private String name;
public User(Long id, String name) {
this.id = id;
this.name = name;
}
// getter/setter
}
控制器调用示例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RestController
@RequestMapping("/async")
public class AsyncController {
@Autowired
private AsyncService asyncService;
@Autowired
private AsyncResultService asyncResultService;
// 无返回值的异步调用
@GetMapping("/send-email")
public String sendEmail(@RequestParam String email) {
System.out.println("主线程: " + Thread.currentThread().getName());
// 异步调用,立即返回
asyncService.sendEmail(email);
return "邮件已开始发送";
}
// 带返回值的异步调用
@GetMapping("/process/{data}")
public String processData(@PathVariable String data) throws ExecutionException, InterruptedException {
Future<String> future = asyncResultService.processData(data);
// 检查是否完成
if (future.isDone()) {
return future.get(); // 获取结果
} else {
return "正在处理中...";
}
}
// 等待异步结果
@GetMapping("/wait-result/{data}")
public String waitForResult(@PathVariable String data) throws ExecutionException, InterruptedException {
Future<String> future = asyncResultService.processData(data);
// 等待结果,最多等待5秒
String result = future.get(); // 阻塞直到结果返回
return result;
}
}
完整的实际应用案例
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class OrderService {
/**
* 异步处理订单
*/
@Async("taskExecutor")
public CompletableFuture<OrderResult> processOrderAsync(Order order) {
OrderResult result = new OrderResult();
try {
// 1. 验证订单
validateOrder(order);
// 2. 处理支付
processPayment(order);
// 3. 更新库存
updateInventory(order);
// 4. 发送通知
sendNotification(order);
result.setSuccess(true);
result.setOrderId(order.getId());
result.setMessage("订单处理成功");
} catch (Exception e) {
result.setSuccess(false);
result.setMessage("订单处理失败: " + e.getMessage());
}
return CompletableFuture.completedFuture(result);
}
private void validateOrder(Order order) {
// 验证逻辑
System.out.println("验证订单: " + order.getId());
}
private void processPayment(Order order) {
// 支付逻辑
System.out.println("处理支付: " + order.getId());
}
private void updateInventory(Order order) {
// 库存逻辑
System.out.println("更新库存: " + order.getId());
}
private void sendNotification(Order order) {
// 通知逻辑
System.out.println("发送通知: " + order.getId());
}
}
// 订单结果类
class OrderResult {
private boolean success;
private Long orderId;
private String message;
// getter/setter
}
注意事项
// 重要:异步方法的限制
@Service
public class AsyncDemoService {
// 错误示例:同一类中调用异步方法不会生效
public void methodA() {
this.methodB(); // 不会异步执行!
}
@Async
public void methodB() {
// 异步逻辑
}
// 正确示例:注入自身
@Autowired
private AsyncDemoService self;
public void methodC() {
self.methodB(); // 会异步执行
}
}
异常处理
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
@Configuration
public class AsyncExceptionConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
// 返回自定义线程池
return null;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println("异步方法异常: " + method.getName());
System.out.println("异常信息: " + ex.getMessage());
// 记录日志或发送通知
}
};
}
}
使用@Async注解实现异步的关键点:
- 启用注解:使用
@EnableAsync - 配置线程池:自定义线程池避免使用默认的SimpleAsyncTaskExecutor
- 方法调用:异步方法必须在外部类调用,同一类内调用无效
- 返回值:使用
Future或CompletableFuture获取异步结果 - 异常处理:实现
AsyncUncaughtExceptionHandler处理未捕获的异常
这个框架广泛用于邮件发送、报表生成、大数据处理等耗时操作。