Spring @Async

news2024/9/27 21:20:34

在Spring中可以使用@Async注解标记类或方法,有@Async注解的类会生成代理对象,代理对象会将有@Async注解的方法(异步方法)放在线程池里面异步执行;

@Async注解的方法返回值类型可以是void,也可以是Future类型,如果是普通类型则获取不到异步执行结果;

Spring默认使用的SimpleAsyncTaskExecutor线程池不会重用线程,并且没有最大线程数的限制,在大并发量的时候存在性能问题,所以Spring使用自定义线程池配合@Async注解一起使用;

一 简单使用

在配置类中添加@EnableAsync注解;

在业务类中需要异步执行的方法上添加@Async注解;

1.1 方法返回值类型是void

@Configuration
@EnableAsync
public class CommonConfig {

}

@Service
public class OrderService {
    public void printOrderMsgOne() {
        try {
            // 模拟线程任务执行
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message one...");
    }

    @Async
    public void printOrderMsgTwo() {
        try {
            // 模拟线程任务执行
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message two...");
    }
}

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/one")
    public String orderOne() {
        System.out.println(Thread.currentThread().getName()
                + " 线程开始执行任务...");
        System.out.println("输出printOrderMsgOne方法信息: ");
        orderService.printOrderMsgOne();
        System.out.println("输出printOrderMsgTwo方法信息: ");
        orderService.printOrderMsgTwo();
        // 模拟线程任务执行
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + " 线程结束执行任务...");
        return "success";
    }

}

方法执行结果:

http-nio-8081-exec-2 线程开始执行任务...
输出printOrderMsgOne方法信息: 
    http-nio-8081-exec-2 输出message one...
输出printOrderMsgTwo方法信息: 
http-nio-8081-exec-2 线程结束执行任务...
    task-1 输出message two...

orderOne方法在http-nio-8081-exec-2线程中执行,printOrderMsgTwo方法在task-1个线程异步执行;

1.2 方法返回值类型是普通类型

@Configuration
@EnableAsync
public class CommonConfig {

}

@Service
public class OrderService {
    public void printOrderMsgOne() {
        try {
            // 模拟线程任务执行
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message one...");
    }

    @Async
    public String printOrderMsgTwo() {
        try {
            // 模拟线程任务执行
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message two...");
        return "printOrderMsgTwo successfully";
    }
}

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/one")
    public String orderOne() {
        System.out.println(Thread.currentThread().getName()
                + " 线程开始执行任务...");
        System.out.println("输出printOrderMsgOne方法信息: ");
        orderService.printOrderMsgOne();
        System.out.println("输出printOrderMsgTwo方法信息: ");
        String str = orderService.printOrderMsgTwo();
        // 模拟线程任务执行
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("异步执行结果: " + str);
        System.out.println(Thread.currentThread().getName()
                + " 线程结束执行任务...");
        return "success";
    }

}

方法执行结果:

http-nio-8081-exec-1 线程开始执行任务...
输出printOrderMsgOne方法信息: 
    http-nio-8081-exec-1 输出message one...
输出printOrderMsgTwo方法信息: 
异步执行结果: null
http-nio-8081-exec-1 线程结束执行任务...
    task-1 输出message two...

在orderOne方法中获取不到printOrderMsgTwo方法异步执行的结果,无论printOrderMsgTwo方法在orderOne方法响应之前完成还是之后完成,都获取不到printOrderMsgTwo方法的异步执行结果;

1.3 方法返回值类型是Future

@Configuration
@EnableAsync
public class CommonConfig {

}

@Service
public class OrderService {
    public void printOrderMsgOne() {
        try {
            // 模拟线程任务执行
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message one...");
    }

    @Async
    public Future<String> printOrderMsgTwo() {
        try {
            // 模拟线程任务执行
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message two...");
        return new AsyncResult<>("printOrderMsgTwo successfully");
    }
}

@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/one")
    public String orderOne() {
        System.out.println(Thread.currentThread().getName()
                + " 线程开始执行任务...");
        System.out.println("输出printOrderMsgOne方法信息: ");
        orderService.printOrderMsgOne();
        System.out.println("输出printOrderMsgTwo方法信息: ");
        Future<String> future = orderService.printOrderMsgTwo();
        // 模拟线程任务执行
        try {
            Thread.sleep(3000);
            String str = future.get();
            System.out.println("异步执行结果: " + str);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + " 线程结束执行任务...");
        return "success";
    }

}

方法执行结果:

http-nio-8081-exec-2 线程开始执行任务...
输出printOrderMsgOne方法信息: 
    http-nio-8081-exec-2 输出message one...
输出printOrderMsgTwo方法信息: 
    task-2 输出message two...
异步执行结果: printOrderMsgTwo successfully
http-nio-8081-exec-2 线程结束执行任务...

orderOne方法在http-nio-8081-exec-2线程中执行,printOrderMsgTwo在task-2线程中执行;

printOrderMsgTwo的方法返回值类型是Future,Future中的get方法是阻塞方法,所以orderOne方法会一直阻塞直到获得异步执行结果才会响应;

二 自定义线程池

@Async注解的value属性用来指定使用具体的线程池

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
    String value() default "";
}
@Configuration
@EnableAsync
public class CommonConfig {

    @Bean("threadPoolOne")
    public ThreadPoolTaskExecutor threadPool() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(10);
        threadPool.setMaxPoolSize(15);
        threadPool.setQueueCapacity(15);
        threadPool.setKeepAliveSeconds(60);
        return threadPool;
    }

    @Bean("threadPoolTwo")
    public ThreadPoolTaskExecutor threadPoolTwo() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(10);
        threadPool.setMaxPoolSize(15);
        threadPool.setQueueCapacity(15);
        threadPool.setKeepAliveSeconds(60);
        return threadPool;
    }

}

@Service
public class OrderService {
    public void printOrderMsgOne() {
        try {
            // 模拟线程任务执行
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message one...");
    }

    @Async("threadPoolTwo")
    public CompletableFuture<String> printOrderMsgTwo() {
        try {
            // 模拟线程任务执行
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("\t" + Thread.currentThread().getName()
                + " 输出message two...");
        return CompletableFuture.completedFuture("printOrderMsgTwo successfully");
    }
}


@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @GetMapping("/one")
    public String orderOne() {
        System.out.println(Thread.currentThread().getName()
                + " 线程开始执行任务...");
        System.out.println("输出printOrderMsgOne方法信息: ");
        orderService.printOrderMsgOne();
        System.out.println("输出printOrderMsgTwo方法信息: ");
        CompletableFuture<String> future = orderService.printOrderMsgTwo();
        // 模拟线程任务执行
        try {
            Thread.sleep(3000);
            String str = future.get();
            System.out.println("异步执行结果: " + str);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()
                + " 线程结束执行任务...");
        return "success";
    }

}

方法执行结果:

http-nio-8081-exec-1 线程开始执行任务...
输出printOrderMsgOne方法信息: 
    http-nio-8081-exec-1 输出message one...
输出printOrderMsgTwo方法信息: 
    threadPoolTwo-1 输出message two...
异步执行结果: printOrderMsgTwo successfully
http-nio-8081-exec-1 线程结束执行任务...

orderOne方法用的是http-nio-8081-exec-1线程,printOrderMsgTwo方法用的threadPoolTwo线程池里面的线程;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2171089.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

媒界:吉利星瑞百炼成钢,持续引领中国汽车价值向上

秋风送爽绘秋色&#xff0c;出行良辰恰逢时。9月28日至9月29日&#xff0c;2024安行中国汽车安全科技公益巡展迎来尾声&#xff0c;安行中国携手吉利汽车&#xff0c;步履轻盈地踏入苏州星湖天街&#xff0c;共同呈献一场融合环保科技前沿、安全驾驶理念与深厚文化底蕴的48小时…

使用jQuery处理Ajax

使用jQuery处理Ajax HTTP协议 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议 设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法 所有的WWW文件都必须遵守这个标准 一次HTTP操作称为一个事务&am…

如何使用 CCF Communicator 框架快速开发设备接口

什么是 CCF Communicator Framework&#xff1f; 通信器框架通过封装 CCF 和设备之间的连接&#xff0c;简化了硬件之间的低级消息处理。 举例来说&#xff0c;考虑一下控制软件和硬件设备之间的连接方式。ASCII 串行连接需要使用 TCP 的套接字连接、用于处理设备发送/接收的…

肺癌类器官培养研究概述

前 言 2023年是类器官被《Science》杂志评为年度十大技术的10周年。10年后类器官技术发展迅猛&#xff0c;犹如一颗璀璨的明珠&#xff0c;不断的为生命科学研究揭示新的奥秘&#xff0c;推动生物医学领域不断前行。肺类器官培养条件也在不断完善&#xff0c;在基础和临床研究…

MySQL面试知识汇总

学习链接 创建索引有哪些注意点&#xff1f; 索引应该建在查询频繁的字段&#xff0c;比如where查询、order排序索引的个数应该适量&#xff08;最多64个&#xff09;&#xff0c;索引需要占用空间&#xff0c;更新时也需要维护区分度低的字段&#xff0c;例如性别&#xff0c…

声阔头戴式耳机怎么样?西圣、jBL、声阔头戴式耳机终极pk测评推荐

我们深知&#xff0c;一款优秀的头戴式耳机&#xff0c;不仅仅是音乐的传递者&#xff0c;更是用户情感与个性的延伸。因此&#xff0c;在设计之初&#xff0c;便将极致的佩戴舒适度视为核心追求&#xff0c;通过人体工学的精准设计与优质材料的精心挑选&#xff0c;力求让每一…

Linux 配置与管理 SWAP(虚拟内存)

Linux 配置与管理 SWAP(虚拟内存&#xff09; 一、作用二、创建交换文件&#xff08;以创建一个2GB的交换文件为例&#xff09;1. 创建交换文件2. 设置文件权限2.1. **关于 sudo chmod 600 /root/swapfile 是否一定要执行**2.2. **关于其他用户启动是否没权限用到交换分区** 3.…

大数据电商数仓项目--实战(一)数据准备

第一章 数仓分层 1.1 为什么要分层 1.2 数仓命名规范 1.2.1 表命名 ODS层命名为ods_表名DIM层命名为dim_表名DWD层命名为dwd_表名DWS层命名为dws_表名DWT层命名为dwt_表名ADS层命名为ads_表名临时表命名为tmp_表名 1.2.2 表字段类型 数量类型为bigint金额类型为decimal(16…

猫咪独自在家可以吗?希喂、美的、有哈宠物空气净化器哪款好?

这不是快要国庆了吗&#xff0c;本来计划去旅游的&#xff0c;结果我妈让我假期回家。收拾行李已经很烦了&#xff0c;行李箱旁的猫咪更是让我头疼。我妈因为之前浮毛过敏的事情&#xff0c;禁止我把猫咪再带回家&#xff0c;朋友们也各有计划&#xff0c;甚至连上门喂养都约满…

设备管理与点巡检系统

在现代企业管理中&#xff0c;设备的高效运作至关重要。为此&#xff0c;我们推出了设备管理与点巡检系统&#xff0c;通过自动化管理提升设备使用效率&#xff0c;保障生产安全。 系统特点 设备全生命周期管理 系统涵盖设备的各个阶段&#xff0c;从设备管理、点检、巡检、保…

计算曲线5s1-2的斜率

在行列可自由变换的条件下&#xff0c;平面上的5点结构只有34个 这次将5点结构通过结构加法化成2点结构5s1-4-3-2&#xff0c;并比较5s1-4-3-2的变化规律。 (A,B)---6*n*2---(0,1)(1,0) 分类A和B&#xff0c;A是34个5点结构&#xff0c;让B全是0。当收敛误差为7e-4&#xff0…

Netty源码解析-响应式实现(Reactor模式)

Netty基本介绍&#xff0c;参考 Netty与网络编程 1、Netty如何支持Reactor模式 1.1 主从Reactor模式 实现这种模式需要定义两个EventLoopGroup&#xff0c;bossGroup就是mainReactor&#xff0c; workerGroup就是subReactor&#xff0c; 接着我们进入下图的b.group方法 1.…

Tomcat部署及其优化

目录 一、Tomcat概述 二、Tomcat的组成 三、Tomcat请求过程 四、Tomcat服务部署 五、/usr/local/tomcat/目录下的主要目录说明 六、Tomcat虚拟主机配置 七、Tomcat优化 1.Tomcat配置文件参数优化 2.Tomcat JVM优化 一、Tomcat概述 Tomcat是基于java语言开发&#xff0c…

传知代码-轻量注意力网络实现苹果叶片识别

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 引言 该系统基于EfficientNet与多头自注意力机制&#xff0c;构建了一个高效、精准的苹果叶片识别模型&#xff0c;能够对不同种类的苹果叶片进行准确分类。通过结合EfficientNet的强大特征提取能力和多头注意力…

Ks渲染做汽车动画吗?汽车本地渲染与云渲染成本分析

Keyshot是一款强大的实时光线追踪和全域光渲染软件&#xff0c;它确实可以用于制作汽车动画&#xff0c;包括汽车模型的渲染和动画展示。Keyshot的动画功能允许用户创建相机移动、物体变化等动态效果&#xff0c;非常适合用于汽车动画的制作。 至于汽车动画的渲染成本&#xff…

Power Platform开发小技巧,一天一个APP, 如何快速搭建二维码识别器

之前&#xff0c;给大家分享了微软Power Platform开发课程——手把手教你搭建二维码生成器&#xff0c;很多小伙伴反馈真好用。这期我们继续为大家分享Power Platform的开发能力与技巧。 今天介绍如何开发⼀个⼆维码识别器。 该应用包含如下功能&#xff1a; 1.⼆维码图片的…

尾矿库安全监测系统:守护矿山安全的关键技术

尾矿库是矿山企业用于存放尾矿的重要设施&#xff0c;其安全状况直接关系到周边环境和人民生命财产安全。近年来&#xff0c;随着技术的不断进步&#xff0c;尾矿库安全监测系统应运而生&#xff0c;为尾矿库的安全管理提供了强有力的技术支持。本文将详细介绍尾矿库安全监测系…

基于spi机制构造的webshell

前言 最近在翻阅yzddmr6师傅博客的时候&#xff0c;发现师傅还有个github的地址 https://github.com/yzddmr6/MyPresentations 里面发现师傅去补天白帽子大会上讲解了一些webshell的攻防&#xff0c;特此进行了学习&#xff0c;然后发现了一个很有意思的webshell&#xff0c…

YOLOv9改进,YOLOv9主干网络替换为PP-LCNetV2(百度飞浆视觉团队自研,轻量化架构),全网独发

摘要 PP-LCNetV2 是在图像分类任务中提出的一种轻量级卷积神经网络,用于在边缘设备上实现高效的推理。PP-LCNet 系列模型的设计旨在提高移动和边缘设备上的推理性能,同时保持较高的准确率。PP-LCNetV2 是在 PP-LCNetV1 基础上改进的。 理论介绍 PP-LCNetV2模型结构如下: …

数据库存储加密技术有哪些 TDE透明加密和列表级加密

透明数据加密&#xff08;TDE&#xff09;和列级加密是数据库加密中两种常见的加密方式&#xff0c;它们在加密范围、实现方式以及对应用程序的影响等方面存在明显的区别。 透明数据加密&#xff08;TDE&#xff09; 定义&#xff1a; 透明数据加密&#xff08;Transparent …