springboot中@Async做异步操作(Completable异步+ThreadPoolTaskExecutor线程池+@Async注解)

前置

@Async用于实现方法级别的异步执行,本质是将方法调用交给后台线程池执行,从而避免阻塞主线程,提升系统的吞吐量和响应速度

强烈建议使用 @Async 时候,需要自定义线程池!

  • 如果是一般 java 项目,现在更多是使用 CompletableFuture 配合上 ExecutorService 开启异步操作
  • 如果是 java springboot web 项目,更多的是使用 @Async 配合上 ThreadPoolTaskExecutor 配置线程池和结合 CompletableFuture 一起做异步操作

启用异步支持

要使用 @Async,首先需要在 Spring 配置类或启动类上添加 @EnableAsync 注解,以启用异步功能
@EnableAsync // 启用异步支持

编写异步方法

在需要异步执行的方法上添加 @Async 注解,该方法必须是 spring 管理的 bean 中的方法,方法也不能是 final,private 这种

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class EmailService {

    @Async  // 标记为异步方法
    public void sendEmail(String emailContent) {
        try {
            // 模拟发送邮件耗时操作
            Thread.sleep(2000);
            System.out.println("邮件发送完成,内容:" + emailContent);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

关于线程池(强烈建议自定义线程池!)

默认情况下,@Async 使用 Spring 的 SimpleAsyncTaskExecutor 线程池(最大线程数为 Integer.MAX_VALUE),一旦请求激增,有可能会导致 cpu 陡增和内存陡增,导致服务崩溃

强烈建议自定义线程池!

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig {
    @Bean(name = "customTaskExecutor")
    public ThreadPoolTaskExecutor customTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);          // 核心线程数
        executor.setMaxPoolSize(10);           // 最大线程数
        executor.setQueueCapacity(100);        // 队列容量,避免无边界队列
        executor.setThreadNamePrefix("Async-"); // 线程名称前缀
        executor.initialize();
        return executor;
    }
}

在 @Async 注解中通过 value 参数指定线程池名称:

@Async("customTaskExecutor")  // 使用自定义线程池
public void sendEmail(String emailContent) {
    // ...
}

为什么 @Async 异步未生效?

  • 未启用 @EnableAsync:检查启动类或配置类是否缺少 @EnableAsync
  • 如果方法在同一个类中被调用,@Async 会失效(Spring 通过代理实现异步,内部调用不走代理)
  • @Async 方法不能是 private 或 final

异步方法的异常怎么处理

异步方法中的异常不会传播到调用方,建议在方法内部捕获并记录

@Async
public void sendEmail(String content) {
    try {
        // 业务逻辑
    } catch (Exception e) {
        // 记录日志
        System.err.println("异步任务异常: " + e.getMessage());
    }
}

异步方法的返回值

@Async 方法可以返回 void 或 Future<T>
Future.get()能获取结果,但是会阻塞主线程

使用场景举例子

常结合 CompletableFuture 使用

@Async
public CompletableFuture<User> getUserAsync(Long userId) {
    // 调用用户服务
}

@Async
public CompletableFuture<Order> getOrderAsync(Long userId) {
    // 调用订单服务
}

// 聚合结果
public void aggregateData(Long userId) {
    CompletableFuture<User> userFuture = getUserAsync(userId);
    CompletableFuture<Order> orderFuture = getOrderAsync(userId);

    userFuture.thenCombine(orderFuture, (user, order) -> {
        // 处理聚合结果
        return new UserProfile(user, order);
    });
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

abcnull

您的打赏是我创作的动力之一

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值