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 异步结果获取,代码更简洁。
相关推荐
rannn_1112 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
IKUN家族4 小时前
Spring IoC&DI
java·spring·rpc
山荷枝5 小时前
03-框架--Spring
java·后端·spring
ChaHae-In6 小时前
SpringBoot统一功能处理
java·spring boot·后端
coder!mq6 小时前
说几个常见的语法糖?
java·开发语言·算法
gugucoding6 小时前
38. 【Java】Stream API(下):高级操作与性能
java·开发语言
心平气和量大福大7 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
952367 小时前
Spring-cloud配置中心
java·spring·spring cloud·微服务
ydd1001008 小时前
寻找两个正序数组的中位数 Java 题解,二分分割详解
java·开发语言
真上帝的左手9 小时前
10. 软件设计&架构-Spring Security 7 整合CAS SSO 单点登录
java·spring·架构·sso