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 异步结果获取,代码更简洁。
相关推荐
xcl09257 小时前
商超智能运营实战:数据驱动提升门店效率与体验指南
java·mfc·宠物
Flynt9 小时前
OpenJDK禁AI代码半年了,现在执行得怎么样?答案是:全靠自觉
java·开源·ai编程
kyriewen12 小时前
我把今年流传的前端 AI 面试题整理了一遍——4 类场景题+回答框架(附速查表)
前端·面试·程序员
AEI14 小时前
四年间大模型的演进历程
人工智能·面试·程序员
古法安卓14 小时前
Android-日志系统源码解析
android·java·android studio
小夏coding15 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端
MacroZheng16 小时前
同事问我:"Claude Code经常失忆,不怕它把项目搞炸?",我:"怕,三个Markdown文件给它装个永不丢失的外置大脑!"
java·人工智能·后端
学习星球17 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
十年Java程序媛18 小时前
深度实战:JDK21 虚拟线程 + HikariCP 生产正确配比、坑点、监控全套
java·spring boot
xiaoqiMikko18 小时前
有人在搜一个不存在的 Tomcat 版本
java·tomcat