Spring @Async 典型用法

典型用法

⚠️ 注意:@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);
}
相关推荐
二哈赛车手5 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~5 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8295 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
星星也在雾里6 小时前
PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控
数据库·postgresql
未若君雅裁7 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记8 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI8 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城20248 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列
常常有8 小时前
MySQL 底层执行原理:输入SQL语句到两阶段提交
数据库·sql·mysql