系统优化-异步化

news2024/9/23 11:17:45

目录

1:异步化

1.1:什么是同步?什么是异步?

1.2:异步化业务流程分析

1.3:异步化的问题 

2:线程池的理论和实战

2.1:为啥需要线程池?

2.2:线程池的实现 

2.2.1:线程池参数

2.2.2:线程池的工作机制 


1:异步化

什么时候使用异步化?

调用的服务处理能力有限,或者处理时间(或返回时)较长时,应该考虑异步化。

1.1:什么是同步?什么是异步?

同步:一件事情做完,再做另一件事情。(烧水后处理工作)

异步:不用等一件事做完,就可以做另一件事,等第一件事情完成时,可以收到一个通知,可以进行后续处理。(烧水的时候,烧水人可以同时处理工作,当烧水完成时,可以听到水壶的蜂鸣声,就知道水烧好了)


1.2:异步化业务流程分析

标准异步化业务流程:

1:当用户要进行耗时很长的操作时,点击提交后,不需要在界面进行等待,而是把这个任务保存到数据库中,记录下来。

2:用户要执行新任务时:

3:线程从任务队列中取出任务依次执行,每完成一个任务需要修改任务的状态。

4:用户可以查询任务的状态,或者在任务执行或失败的时候能够得到通知。

5:如果执行的任务非常复杂,包括很多环节,在每完成一个任务时,要在程序(数据库中)记录一下任务的执行流程。


本次项目业务异步化的执行流程:

1:用户点击智能分析的提交按钮时,先把图表立刻保存到数据库中(作为一个任务) 

2:用户可以在图表管理页面查看所有图表(已生成的,生成中的,生成失败)的信息和状态。

1:将用户从前端传过来的数据保存到数据库中

2:生成图表的任务放到任务队列中

3:任务处理模块再去从任务队列中取出图表任务,交给AI进行分析,一个一个进行分析。 

4:AI处理完一个项目,给任务处理模块一个通知,任务处理模块更新数据库中的状态。

1.3:异步化的问题 

 1.3.1:任务队列的最大容量

1.3.2:怎样从任务队列中取出任务去执行?任务队列的流程怎样实现?

以上两个问题可以利用线程池来进行解决。

2:线程池的理论和实战

2.1:为啥需要线程池?

1:线程的管理比较复杂(eg:比如什么时候新增线程,什么时候减少空闲线程)

2:任务存取比较复杂(eg:什么时候接收任务,什么时候拒绝任务,怎么保证大家不抢到同一个任务)

线程池的作用:帮助我们轻松管理线程,协调任务的执行进程。

 

2.2:线程池的实现 

在Spring中,可以用ThreadPoolTaskExecutor配合@Async注解来实现。(不太建议)

在Java中,可以使用JUC并发编程包中的ThreadPoolExecutor来实现。(建议)

2.2.1:线程池参数

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) 

2.2.2:线程池的工作机制 

 

 

当已经达到了最大线程数,此时,任务队列中也没有新的任务要去执行,那么等keepAlive时间达到后,就可以将这个线程释放。 

线程池参数如何设置?

首先,根据自己当前的业务或者系统进行执行。

一般情况下,任务分为IO密集型和计算密集型两种。

计算密集型:吃CPU ,比如音视频处理,图像处理,数学计算等,一般设置为corePoolSize为CPU核数+1,可以让每个线程都利用CPU的每个核,而且线程之间不用频繁切换

IO密集型:吃带宽/内存/硬盘的读写资源,corePoolSize可以设置大一点(2*n+1)

考虑导入百万数据到数据库,属于IO密集型任务,还是计算密集型任务?

属于IO密集型任务,因为在这个工作中,吃的是带宽/内存/硬盘的资源。 


代码校验线程池的工作机制: 

a:相关参数设置,我们用的是一个config的目录下的类,相当于公共的类。

@Configuration
public class ThreadPoolExecutorConfig {
    @Bean
    public ThreadPoolExecutor threadPoolExecutor(){
        ThreadFactory threadFactory=new ThreadFactory() {
            private int count=1;
            @Override
            public Thread newThread(@NotNull Runnable r) {
             Thread thread=new Thread(r);
             thread.setName("线程"+count);
             return thread;
            }
        };
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2,4,100, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(4),threadFactory);
        return threadPoolExecutor;
    }

}

b:我们在controller层新建一个类用来提交任务和检验任务。 

@RestController
@RequestMapping("/queue")
@Slf4j
public class QueueController {
   @Autowired
   private ThreadPoolExecutor threadPoolExecutor;
   //添加任务的接口,提交任务
    @GetMapping("/add")//添加任务的接口
    public void  add(String name){

        CompletableFuture.runAsync(()->{
            log.info("任务执行中:"+name+". 执行人 "+ Thread.currentThread().getName());
            try {
                Thread.sleep(600000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        },threadPoolExecutor);

    };
    //查看线程池的状态
    @GetMapping("/get")
    public String get(){
        Map<String,Object> map=new HashMap<>();
        int size=threadPoolExecutor.getQueue().size();
        map.put("队列长度",size);
        long taskCount = threadPoolExecutor.getTaskCount();//任务总数
        map.put("任务的总数量",taskCount);
        long completedTaskCount = threadPoolExecutor.getCompletedTaskCount();//已经成功的任务数
        map.put("已经完成的任务数",completedTaskCount);
        int activeCount = threadPoolExecutor.getActiveCount();//正在工作的员工数
        map.put("正在工作的线程数",activeCount);
        return JSONUtil.toJsonStr(map);
    }
}

 

c:利用 swagger生成的接口文档进行校验:

a):当发送任务1时,我们设置的核心线程数为2

利用接口文档来进行发送和校验:

b):当发送任务2时,我们设置的核心线程数为2

利用接口文档来进行发送和校验: 

 

 c):当发送任务3时,我们设置的核心线程数为2,此时,正式的线程数已经用完了,根据线程池的工作机制应该加到任务队列中,我们来进行查看。任务3此时并没有线程来进行执行。而是加到了任务队列中。

 

d):当任务队列满时,此时正式线程数也已经满了,看看啥情况,即任务数到达6了,继续再发一个任务。

 

 

此时,就会调用临时的线程来执行任务。

 当达到整个maxpoolSize且阻塞队列满时,就会进行报错。

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

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

相关文章

酷开科技 | 酷开系统大屏电视,打造精彩家庭场景

在信息资讯不发达的年代&#xff0c;电视机一直都是个人及家庭重要的信息获取渠道和家庭娱乐中心&#xff0c;是每个家庭必不可少的大家电之一&#xff01;在快节奏的现代生活中&#xff0c;受手机和平板的冲击&#xff0c;电视机这个曾经的客厅“霸主”一度失去了“主角光环”…

Haproxy 服务

Haproxy&#xff1a;他也是常用的负载均衡软件 nginx 支持四层转发&#xff0c;七层转发 haproxy 也是四层和七层转发 LVS的DR和NAT都是基于四层转发 都是基于流量的转发。 tun:四层和七层都有。 基于四层的转发&#xff1a; 1&#xff0c;lvs 2&#xff0c;nginx 3&…

Go语言入门心法(十六):Go远程过程调用框架GRPC实战

Go语言入门心法(一): 基础语法 Go语言入门心法(二): 结构体 Go语言入门心法(三): 接口 Go语言入门心法(四): 异常体系 Go语言入门心法(五): 函数 Go语言入门心法(六): HTTP面向客户端|服务端编程 Go语言入门心法(七): 并发与通道 Go语言入门心法(八): mysql驱动安装报错o…

vue-admin相关问题记录

编辑器设置自定义高度 base.component.js内关于tinymce内容初始化设置&#xff0c;增加高度自定义接收并初始化 <tinymce :content.sync"form.article_content" :height"400"></tinymce> textarea自定义高度 tooltip备注

Python数据结构(树)

Python数据结构&#xff08;树&#xff09; 树的概念 树(英语: tree)是一种抽象数据类型ADT) 或是实作这种抽象数据类型的数据结构&#xff0c;用来模拟具有树状结构性质的数据集合。它是由n(n>1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一…

Elasticsearch核心技术与实战-05-elasticsearch的安装与简单配置-Windows

首先下载elasticsearch的zip包&#xff1a;下载地址 网络不通的解决方法&#xff1a;国内镜像站 es、kibana、logstash均可在华为云开元镜像站自行选择版本下载&#xff1a;下载地址 下载插件包&#xff1a; .\bin\elasticsearch-plugin install analysis-icu .\bin\elasti…

ORB-SLAM系列算法相关介绍(综合版)

一、参考资料 ORB-SLAM2详解&#xff08;一&#xff09;简介 &#xff08;公开课&#xff09;视觉SLAM原理与ORB-SLAM3系列算法 二、相关介绍 1. ORB简介 ORB指的是一种旋转不变性特征。 2. ORB-SLAM系列算法的演进 三、ORB-SLAM 论文&#xff1a;ORB-SLAM: A Versatile …

php使用lunar实现农历、阳历、节日等功能

lunar是一个支持阳历、阴历、佛历和道历的日历工具库&#xff0c;它开源免费&#xff0c;有多种开发语言的版本&#xff0c;不依赖第三方&#xff0c;支持阳历、阴历、佛历、道历、儒略日的相互转换&#xff0c;还支持星座、干支、生肖等。仅供参考&#xff0c;切勿迷信。 官…

相机卡格式化了还能恢复吗?答案在这!(附带恢复教程)

“天啊&#xff01;和朋友出去旅行拍了好多美美的照片&#xff0c;在传照片的时候不小心点到了格式化&#xff0c;相机里所有的照片都被清空了&#xff01;这可怎么办呀&#xff1f;相机卡被格式化了还有机会恢复吗&#xff1f;” 相机的存储卡通常会保存我们很多美好的记忆&am…

某网站互动数据采集

1&#xff0c;网址 aHR0cHM6Ly9uZXdzLmZ1dHVubi5jb20vcG9zdC8zMzE4MzE1OQ2&#xff0c;找到返回互动数的请求包 3&#xff0c;采集互动数据加密信息如下 4&#xff0c;察看抓到的包&#xff0c;不难发现futu-offline-csrf-v2和futu-x-csrf-token-v2这两个参数在首页的请求中有…

vue2.0项目中组件和iframe之间如何传值

vue2.0项目中组件和iframe之间如何传值 一、vue组件二、iframe组件 一、vue组件 mounted() {// 注册 message 事件监听器&#xff0c;只注册一次window.addEventListener(message, this.handleFromIframeMessage) }, beforeDestroy() {// 移除事件监听器window.removeEventList…

测开( 进阶篇)

目录 按测试对象进行划分 界面测试 可靠性测试 容错性 灾难恢复性测试 - 了解即可 文档测试 兼容性测试 易用性测试 安装卸载测试 安全测试 性能测试 内存泄漏测试 实战 - 微信发红包的测试用例 按是否查看代码划分 黑盒测试(Black-box Testing) 白盒测试(Whit…

02333软件工程串讲

完整笔记在语雀 https://www.yuque.com/huangzhanqi/nrt1l4/zoa0g0osnrmog0xdhttps://www.yuque.com/huangzhanqi/nrt1l4/zoa0g0osnrmog0xd 《软件工程》串讲讲义 应考指导 一、课程介绍 1、课程性质 《软件工程》是全国高等教育自学考试计算机及应用&#xff08;独立本科…

Leo赠书活动-01期 【Python数据挖掘——入门进阶与实用案例分析】

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

隧道代理 vs 普通代理:哪种更适合您的爬虫应用?

前言 随着互联网的普及&#xff0c;爬虫技术在多个领域得到广泛应用。在进行爬虫开发时&#xff0c;代理服务器是不可或缺的工具之一。代理服务器可以隐藏客户端的真实 IP 地址和位置&#xff0c;从而保护客户端的隐私&#xff0c;同时通过代理可以绕过一些网络限制和安全机制…

重生奇迹mu血色城堡攻略教程

重生奇迹mu血色城堡所需道具 血色城堡位于冰风谷的基地内&#xff0c;具体坐标是209&#xff0c;30&#xff0c;玩家找到此处大天使的使者后&#xff0c;与其对话并携带好相应的道具&#xff0c;便能在活动开启后进入血色城堡。进入城堡需要与你等级对应的透明披风&#xff0c…

再获Gartner权威认可!安全狗作为CWPP代表厂商入选《2023中国网络安全技术成熟度曲线》报告

近日&#xff0c;国际权威研究机构Gartner发布了《2023中国网络安全技术成熟度曲线》&#xff08;Hype Cycle for Security in China&#xff0c;2023&#xff09;报告。 作为国内云原生安全领导厂商&#xff0c;安全狗也凭借综合且全面的云工作负载安全技术与实力&#xff0c;…

13. 机器学习 - 数据集的处理

文章目录 Training data splitNormalizationStandardizedONE-HOT补充&#xff1a;SOFTMAX 和 CROSS-ENTROPY Hi&#xff0c; 你好。我是茶桁。 上一节课&#xff0c;咱们讲解了『拟合』&#xff0c;了解了什么是过拟合&#xff0c;什么是欠拟合。也说过&#xff0c;如果大家以…

【AGC】更新应用信息报未知错误解决方法

【问题描述】 最近有几个开发者遇到了一个问题&#xff0c;他们在AGC控制台配置好应用信息的图标和截图之后&#xff0c;点击保存按钮会弹出“未知错误&#xff0c;请稍后再试”的异常报错&#xff0c;导致无法正确保存应用配置信息。 出错页面如图所示。 ​​ 【解决方案】 …

基于springboot+vue实现地方美食分享网站项目【项目源码+论文说明】计算机毕业设计

基于springbootvue实现地方美食分享网站演示 摘要 首先&#xff0c;论文一开始便是清楚的论述了系统的研究内容。其次&#xff0c;剖析系统需求分析&#xff0c;弄明白“做什么”&#xff0c;分析包括业务分析和业务流程的分析以及用例分析&#xff0c;更进一步明确系统的需求…