SpringBoot异步框架

news2024/9/23 13:30:24

参考:解剖SpringBoot异步线程池框架_哔哩哔哩_bilibili

1、 为什么要用异步框架,它解决什么问题?

在SpringBoot的日常开发中,一般都是同步调用的。但经常有特殊业务需要做异步来处理,例如:注册新用户,送100个积分;或下单成功,发送push消息等。

(1)容错性

如果送积分出现异常,不能因为送积分而导致用户注册失败。

因为用户注册是主要功能,送积分是次要功能,即使送积分异常也要提示用户注册成功,然后后面再针对积分异常做补偿处理。

(2)提升性能

例如注册用户花了20毫秒,送积分花费50毫秒。如果同步的话,总耗时70毫秒,用异常的话,无需等待积分,故耗时20毫秒。

因此,使用异步能解决2个问题:容错性+性能

2、简单异步调用示例

(1)开启异步任务

采用@EnableAsync来开启异步任务支持,另外需要加入@Configuration来把当前类加入springIOC容器中。

SyncConfiguration.java文件:

@Configuration 
@EnableAsync 
public class SyncConfiguration {
}

(2)在方法上标记异步调用

增加一个service类,用来做积分处理

@Async添加在方法上,代表该方法为异步处理

ScoreService.java文件:

public interface ScoreService {
    public void addScore();  // 增加积分

}

ScoreServiceImpl.java文件:

@Service
@Slf4j
public class ScoreServiceImpl implements ScoreService {

    @Async
    @Override
    public void addScore() {
        // 模拟睡5秒,用于赠送积分处理
        try {
            Thread.sleep(5000);
            log.info("--------------------处理积分----------------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

调用测试:

@GetMapping("/sync1")
    public String getAsyncScore(){
        log.info("--------注册用户----------");
        scoreService.addScore();
        return "OK";
    }

连续发送4次请求的日志信息如下:

3、为什么要给@Async自定义线程池

@Async注解,在默认情况下用的是SimpleAsyncTaskExecutor线程池,因为它不是真正的线程池,这个类不重用线程,每次调用都会新建一个新的线程。

可以通过如上日志查看,每次打印的线程名都是[task-1],[task-2], [task-3]……递增的。

我们采用ThreadPoolTaskExecutor,其实质是对java.util.concurrent.ThreadPoolExecutor的包装。

4、为@Async实现一个自定义线程池

(1)配置自定义线程池

SyncConfiguration.java文件:

@Configuration
@EnableAsync
public class SyncConfiguration {

    @Bean(name="scorePoolTaskExecutor")
    public ThreadPoolTaskExecutor getScorePoolTaskExecutor(){
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        taskExecutor.setCorePoolSize(2);
        // 线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        taskExecutor.setMaxPoolSize(4);
        // 缓存队列
        taskExecutor.setQueueCapacity(2);
        // 空闲时间,当超过了核心线程数之外的线程在空闲时间到达之后会被销毁
        taskExecutor.setKeepAliveSeconds(10);
        // 异步方法内部线程名称
        taskExecutor.setThreadNamePrefix("score-");
        // 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到达就会采取的拒绝策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }
}

(2)为@Async指定线程池的名称

ScoreService.java文件:

public interface ScoreService {
    public void addScore();  // 增加积分

    public void addScore2(); // 增加积分测试2
}

ScoreServiceImpl.java文件

@Service
@Slf4j
public class ScoreServiceImpl implements ScoreService {

    @Async
    @Override
    public void addScore() {
        // 模拟睡5秒,用于赠送积分处理
        try {
            Thread.sleep(5000);
            log.info("--------------------处理积分----------------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Async("scorePoolTaskExecutor")
    @Override
    public void addScore2() {
        // 模拟睡5秒,用于赠送积分处理
        try {
            Thread.sleep(5000);
            log.info("--------------------处理积分----------------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

测试类:

@GetMapping("/sync2")
    public String getAsyncScore2(){
        log.info("--------注册用户----------");
        scoreService.addScore2();
        return "OK";
    }

连续调用8次的效果:

可以发现只有两个线程一直在重用。

6、总结

(1)异步的好处:
容错性+性能提升
(2)自定义线程池的方法:
首先,配置类中开启异步任务支持,同时配置线程池策略
其次,异步方法的@Async中指定线程池的名称
 

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

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

相关文章

idea找不到DataBase

一、我想把数据库跟我的idea链接,结果发现找不到。如图。 二、解决方案 找到 file ---setting 找到plugin------找到marketplace 我的已经出现了

贪心-leetcode409最长回文串

贪心-leetcode409最长回文串 思考: 总的思路:从数字中选择个数是偶数的去union,最后如果有过奇数则多union一个作为中心;从数组中select然后feasible是如果该数字为偶数则union到两边,如果为奇数则按照偶数处理再给中…

Java版企业电子招标采购系统源码—企业战略布局下的采购寻源tbms

​ 项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以…

分布式 - 消息队列Kafka:Kafka生产者发送消息的分区策略

文章目录 1. PartitionInfo 分区源码2. Partitioner 分区器接口源码3. 自定义分区策略4. 轮询策略 RoundRobinPartitioner5. 黏性分区策略 UniformStickyPartitioner6. hash分区策略7. 默认分区策略 DefaultPartitioner 分区的作用就是提供负载均衡的能力,或者说对数…

【Shell编程】Linux Shell编程入门:输入输出、变量、条件判断、函数和运算

在Linux操作系统中,Shell编程是一项非常重要的技能。通过Shell编程,我们可以自动化执行各种任务,提高工作效率。无论是系统管理、数据处理还是软件开发,都离不开Shell脚本的应用。本篇博客将带领大家深入了解Shell编程的基础知识&…

木马免杀(篇一)基础知识学习

木马免杀(篇一)基础知识学习 ———— 简单的木马就是一个 exe 文件,比如今年hw流传的一张图:某可疑 exe 文件正在加载。当然木马还可能伪造成各式各样的文件,dll动态链接库文件、lnk快捷方式文件等,也可能…

音视频基础:分辨率、码率、帧率之间关系

基础 人类视觉系统 分辨率 像素: 是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子;可以将像素视为整个图像中不可分割的单位或者是元素;像素…

php通过递归获取分公司的上下级数据

1.表结构 2.php核心代码 /*** param $branches 全部分公司数据* param $parentId 查询的分公司id,传0则全部排序。大于0,则查询该分公司下的下级* param int $level 层级,方便界面特效* param int $level_grade 层级叠加数* return array*/f…

CNN的特性

1、位移不变性 它指的是无论物体在图像中的什么位置,卷积神经网络的识别结果都应该是一样的。 因为CNN就是利用一个kernel在整张图像上不断步进来完成卷积操作的,而且在这个过程中kernel的参数是共享的。换句话说,它其实就是拿了同一张“通…

Docker+rancher部署SkyWalking8.5并应用在springboot服务中

1.Skywalking介绍 Skywalking是一个国产的开源框架,2015年有吴晟个人开源,2017年加入Apache孵化器,国人开源的产品,主要开发人员来自于华为,2019年4月17日Apache董事会批准SkyWalking成为顶级项目,支持Jav…

预测成真,国内传来三个消息,中国年轻人变了,创新力产品崛起

中国的年轻人真的变了! 最近,国内传来三个消息,让外媒的预测成真。 第一,奥迪要开始用国产车的平台了。这里需要说明的是新能源汽车,奥迪也曾多次公开表示,承认了当前中国新能源汽车核心技术上的领先。 第…

【计算机网络】概述及数据链路层

每一层只依赖于下一层所提供的服务,使得各层之间相互独立、灵活性好,已于实现和维护,并能促进标准化工作。 应用层:通过应用进程间的交互完成特定的网络应用,HTTP、FTP、DNS,应用层交互的数据单元被称为报…

java编程规范

一、时间格式为什么有大写有小写呢? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");为了区分月份和分钟,用大写M代表月份,小写m代表分钟 而大写的H代表24小时制,小写h代表12小时制 二、下面的程序判断等值的方式&…

【人工智能前沿弄潮】—— SAM自动生成物体mask

SAM自动生成物体mask 由于SAM可以高效处理提示,可以通过在图像上抽样大量的提示来生成整个图像的mask。这种方法被用来生成数据集SA-1B。 类SamAutomaticMaskGenerator实现了这个功能。它通过在图像上的网格中对单点输入提示进行抽样,从每个提示中SAM可…

基于关系有向图的知识推理2022ACM 8.9

基于关系有向图的知识推理 摘要介绍相关工作基于路径的方法基于GNN的方法 关系有向图RED-GCN实验 摘要 知识图推理旨在从已有的知识中推断出新的事实。基于关系路径的方法在文献中显示出较强的可解释性和归纳推理能力。然而,在KG中 捕获复杂拓扑(Capturing complex…

饮用水除硝酸盐、饮用水除砷、饮用水除氟、饮用水除铁锰的技术汇总

我们所说的“自来水”是指从水龙头里放出来的水。但从水龙头里放出来并不等于安全卫生。实际上,原水必须经过各种处理措施之后才能称为安全卫生的饮用水。每一滴水都要经过了混凝、沉淀、过滤、消毒四个步骤的处理,才能去除杂质和细菌,变得安…

Three.js纹理贴图

目录 Three.js入门 Three.js光源 Three.js阴影 Three.js纹理贴图 纹理是一种图像或图像数据,用于为物体的材质提供颜色、纹理、法线、位移等信息,从而实现更加逼真的渲染结果。 纹理可以应用于Three.js中的材质类型,如MeshBasicMaterial…

本质矩阵E、基本矩阵F、单应矩阵H

1. E (归一化坐标对进行计算) t ^ R 为3*3的矩阵, 因为R,t共有6个自由度,又因为单目尺度等价性,所以实际上E矩阵共有5个自由度。因此至少需要5个点对来求解。 2. 基本矩阵F:根据两帧间匹配的像素点对儿计算 3*3且自由度为7的矩阵kF也为基础矩阵&#x…

构建之法 - 软工教学:每天都向前推进一点点

作者:福州⼤学 汪璟玢⽼师 汪老师:每次都向前推进一点点,哪怕只有一点点,也好过什么都不做。 ​邹老师:对,几个学期下来,就已经超过那些“空想”的团队很远了。坚持下去! 汪老师&…

x86 kgdb deug调试分析

本文主要是收集,以下文章写得很好,我二次整理一下。 如果要手动livedb. 1. call kdbg_arch_late() 2. kgd_set_hw_break(addr,8,1); 3. kgdb_correct_hw_break();// enable bp to cpu regs -------------------------------分割线----------------…