当前位置: 首页 > news >正文

@Async 异步方法,并配置定制线程池

@Async 是 Spring 框架提供的一个注解,用于异步执行方法。它的主要作用是将方法的执行放到一个独立的线程中,从而不会阻塞主线程,提高系统的并发性能和响应速度。


@Async 的作用

  1. 非阻塞执行

    • @Async 注解的方法会在一个独立的线程中执行,调用者无需等待方法执行完成,可以立即返回。
  2. 提高并发性能

    • 适合处理耗时操作(如文件导出、数据上传、复杂计算等),避免阻塞主线程,提升系统的吞吐量。
  3. 简化异步编程

    • 使用 @Async 可以避免手动创建和管理线程,Spring 会自动处理线程池和任务调度。

使用场景

  1. 文件导出

    • 用户发起导出请求后,系统立即返回响应,后台异步生成文件并上传。
  2. 发送通知

    • 发送邮件、短信或站内信时,异步执行以避免阻塞主线程。
  3. 数据处理

    • 对大量数据进行处理或计算时,异步执行以提高效率。
  4. 调用外部服务

    • 调用第三方 API 或服务时,异步执行以避免阻塞主线程。

如何使用 @Async

1. 启用异步支持

在 Spring Boot 启动类或配置类上添加 @EnableAsync 注解:

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
2. 标记异步方法

在需要异步执行的方法上添加 @Async 注解:

@Service
public class MyService {

    @Async
    public void asyncMethod() {
        // 耗时操作
        System.out.println("异步方法执行中,线程:" + Thread.currentThread().getName());
    }
}
3. 调用异步方法

从其他类中调用异步方法时,Spring 会自动将其放到独立线程中执行:

@RestController
public class MyController {

    @Autowired
    private MyService myService;

    @GetMapping("/test")
    public String testAsync() {
        myService.asyncMethod();
        return "异步方法已调用,请查看控制台日志。";
    }
}

注意事项

  1. 返回值

    • 如果异步方法需要返回值,可以使用 FutureCompletableFuture 作为返回类型。
  2. 线程池配置

    • 默认情况下,Spring 使用简单的线程池执行异步任务。可以通过配置自定义线程池:
      @Configuration
      public class AsyncConfig {
      
          @Bean(name = "taskExecutor")
          public Executor taskExecutor() {
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              executor.setCorePoolSize(10);
              executor.setMaxPoolSize(20);
              executor.setQueueCapacity(50);
              executor.setThreadNamePrefix("Async-");
              executor.initialize();
              return executor;
          }
      }
      
    • @Async 注解中指定线程池:
      @Async("taskExecutor")
      public void asyncMethod() {
          // 异步执行
      }
      
  3. 异常处理

    • 异步方法中的异常不会传播到调用者,需要在方法内部处理或通过 AsyncUncaughtExceptionHandler 捕获。
  4. 同类调用失效

    • 如果在一个类中直接调用 @Async 方法,异步不会生效。需要通过 Spring 代理调用(如从另一个类中调用)。

示例:异步导出文件

以下是一个完整的异步导出文件示例:

1. 启用异步支持
@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
2. 异步导出服务
@Service
public class ExportService {

    @Async
    public void exportDataAsync(String fileName, List<ExportData> dataList) {
        try {
            // 生成 Excel 文件
            File file = new File(fileName);
            EasyExcel.write(file, ExportData.class).sheet("Sheet1").doWrite(dataList);

            // 模拟上传至 COS
            System.out.println("文件已生成,开始上传...");
            Thread.sleep(5000); // 模拟上传耗时
            System.out.println("文件上传完成,下载链接:https://example.com/" + fileName);

            // 删除本地临时文件
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
3. 控制器
@RestController
@RequestMapping("/export")
public class ExportController {

    @Autowired
    private ExportService exportService;

    @PostMapping("/start")
    public ResponseEntity<String> startExport() {
        // 模拟数据
        List<ExportData> dataList = new ArrayList<>();
        dataList.add(new ExportData("1", "测试1", "2023-10-01"));
        dataList.add(new ExportData("2", "测试2", "2023-10-02"));

        // 异步导出
        String fileName = "export_data_" + System.currentTimeMillis() + ".xlsx";
        exportService.exportDataAsync(fileName, dataList);

        // 立即返回响应
        return ResponseEntity.ok("导出任务已开始,请稍后查看下载链接。");
    }
}

总结

@Async 是 Spring 提供的强大工具,可以轻松实现异步编程,提升系统性能。通过合理使用 @Async,可以避免阻塞主线程,提高用户体验。如果有其他问题,欢迎随时提问! 😊

相关文章:

  • GitHub免密操作与跨服务器通行:SSH密钥一站式配置指南
  • ubuntu开机自动挂载硬盘
  • 测试用例的Story是什么?
  • uniapp 微信小程序打包之后vendor.js 主包体积太大,解决办法,“subPackages“:true设置不生效
  • 实战技巧:如何快速提高网站收录的权威性?
  • 23种设计模式之《外观模式(Facade)》在c#中的应用及理解
  • Spring高级篇-Spring IOC容器 Aware 接口
  • 一周热点:马斯克让OpenAI变的更加具有变数
  • 牛客周赛 Round 82(思维、差分、树状数组、大根堆、前后缀、递归)
  • 【Linux知识】Linux上从源码编译到软件安装全过程详细说明
  • 1. EXCEL基础、界面介绍《AI赋能Excel 》
  • 基于TensorFlow.js与Web Worker的智能证件照生成方案
  • C++对象模型之C++额外成本
  • 姜雷从萨满非物质文化传承者到跨界融合的成长历程
  • 51单片机编程学习笔记——点亮LED
  • 初阶数据结构(C语言实现)——1数据结构前言
  • LeetCode刷题零碎知识点整理
  • 2024/2/23 考试
  • js中的await与async的使用
  • react使用拖拽,缩放组件,采用react-rnd解决
  • 谷神星一号海射型遥五运载火箭发射成功
  • 无人机企业从科技园区搬到乡村后,村子里变得不一样了
  • 上博东馆常设陈列入选全国博物馆“十大精品”
  • 美国失去最后的AAA主权评级,继标普、惠誉后再遭穆迪降级
  • 马上评|重病老人取款身亡,如何避免类似悲剧?
  • “9+2”复式票,浦东购彩者拿下体彩大乐透1153万头奖