JUC相关的函数、注解、变量杂记

1. @Async的作用

一、核心作用

@Async 是 Spring 提供的异步执行注解,作用:

  1. 把被标注的方法放到独立线程异步执行,不会阻塞当前调用主线程;
  2. 实现任务解耦、提升接口响应速度,常用于异步通知、日志、文件导出、消息发送等耗时操作。

二、使用前提(必须两步,缺一不可)

  1. 启动类添加 @EnableAsync 开启异步功能

java

复制代码
@SpringBootApplication
@EnableAsync // 开启Spring异步支持
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}
  1. @Async 写在public 方法上,且调用方和异步方法不在同一个类(内部调用不生效,AOP 无法拦截)

三、两种返回形式

1. 无返回值(void)

适合不需要接收结果的耗时任务:发短信、记录操作日志

java

复制代码
@Async
public void sendSms(String phone) {
    // 耗时网络操作,异步执行,不阻塞主线程
}

2. 有返回值(返回 Future<T> / CompletableFuture<T>)

需要获取异步执行结果、做结果聚合

java

复制代码
@Async
public Future<Integer> countOrder() {
    int total = orderMapper.selectCount(null);
    return CompletableFuture.completedFuture(total);
}

// 调用
Future<Integer> future = orderService.countOrder();
Integer total = future.get(); // 阻塞等待异步结果

四、底层原理

Spring 通过 AOP 动态代理 拦截 @Async 方法:

  1. 拦截到方法后,把任务交给内置线程池 SimpleAsyncTaskExecutor
  2. 新开子线程执行目标方法,主线程直接返回,不等待方法执行完毕。

五、默认线程池问题(重要)

默认使用 SimpleAsyncTaskExecutor每次调用新建一个线程,无复用、无限创建线程,高并发会 OOM。

生产环境自定义线程池方案

java

复制代码
@Configuration
public class AsyncConfig {
    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);    // 核心线程
        executor.setMaxPoolSize(50);     // 最大线程
        executor.setQueueCapacity(200);  // 队列
        executor.setThreadNamePrefix("async-task-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

// 指定使用自定义线程池
@Async("taskExecutor")
public void asyncTask(){}

六、常见坑

  1. 同类内部调用失效

java

复制代码
// 同一个类里调用,AOP代理拦截不到,同步执行
public void test(){
    asyncMethod(); // 无效,同步
}
@Async
public void asyncMethod(){}

解决:把异步方法抽离到单独 Service,或者通过 ApplicationContext 获取代理对象调用。

  1. 事务失效异步方法会新开线程,子线程和主线程是独立事务,主线程回滚不影响异步方法。

  2. 异常捕获void 异步方法抛出异常主线程感知不到,需要自定义 AsyncUncaughtExceptionHandler 统一捕获异常告警。

  3. 事务传播问题主线程事务不会传递到异步子线程,各自独立。

七、适用场景 & 不适用场景

适用

  • 异步通知:短信、邮件、站内信
  • 后置统计:操作日志、埋点数据上报
  • 耗时计算:报表生成、大数据导出
  • MQ 消息异步发送

不适用

  • 需要同步事务保证一致性的核心业务(订单创建 + 库存扣减不能分开异步)
  • 需要实时拿到返回结果且不能阻塞的简单接口(同步即可)

八、和手动创建线程的区别

  1. @Async 托管线程池,统一管控、可配置拒绝策略;
  2. 统一异常处理、线程复用,不用手动管理 Thread;
  3. 支持返回 Future 异步结果获取,代码更简洁。
相关推荐
小羊没烦恼!1 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里1 天前
java中的继承和多态的区别
java
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕1 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码1 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖1 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时1 天前
01-06-A-JVM排查实战详解
java·jvm
晨米酱1 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
vipxieliang1 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
ba_pi1 天前
mysql 查询所有表名并授权
java