系统优化-异步化

简介: 系统优化-异步化

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且阻塞队列满时,就会进行报错。

相关文章
|
1月前
|
人工智能 供应链 数据可视化
一文读懂AI引擎与Together规则引擎重塑智能决策
从1950年图灵提出人工智能设想到如今AI引擎实现自主决策,Together规则引擎正成为智能决策核心。它通过动态规划、多工具调用与持续学习机制,赋能供应链、财务、定价等场景,提升决策透明度与效率。Together助力AI引擎突破落地瓶颈,推动企业管理迈向“决策即服务”新时代。
|
2月前
|
机器学习/深度学习 人工智能 搜索推荐
思维树提示技术:让AI像人类一样思考的魔法
想象一下,如果AI能像你思考问题一样有条理,从一个想法延伸到多个分支,会发生什么?思维树提示技术就是这样一种让AI更聪明的方法,通过结构化思维引导,让AI等大模型给出更深入、更全面的回答。本文将用最轻松的方式,带你掌握这个让AI智商飞升的秘技。
|
21天前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
318 100
|
21天前
|
机器学习/深度学习 人工智能 自然语言处理
Transformer架构:重塑现代AI的核心引擎
Transformer架构:重塑现代AI的核心引擎
317 98
|
21天前
|
存储 人工智能 自然语言处理
RAG:增强大模型知识库的新范式
RAG:增强大模型知识库的新范式
376 99
|
15天前
|
人工智能 监控 测试技术
告别只会写提示词:构建生产级LLM系统的完整架构图​
本文系统梳理了从提示词到生产级LLM产品的八大核心能力:提示词工程、上下文工程、微调、RAG、智能体开发、部署、优化与可观测性,助你构建可落地、可迭代的AI产品体系。
253 51
|
15天前
|
人工智能 数据可视化 数据处理
AI智能体框架怎么选?7个主流工具详细对比解析
大语言模型需借助AI智能体实现“理解”到“行动”的跨越。本文解析主流智能体框架,从RelevanceAI、smolagents到LangGraph,涵盖技术门槛、任务复杂度、社区生态等选型关键因素,助你根据项目需求选择最合适的开发工具,构建高效、可扩展的智能系统。
302 3
AI智能体框架怎么选?7个主流工具详细对比解析
|
1月前
|
机器学习/深度学习 存储 资源调度
Transformer架构的简要解析
Transformer架构自2017年提出以来,彻底革新了人工智能领域,广泛应用于自然语言处理、语音识别等任务。其核心创新在于自注意力机制,通过计算序列中任意两个位置的相关性,打破了传统循环神经网络的序列依赖限制,实现了高效并行化与长距离依赖建模。该架构由编码器和解码器组成,结合多头注意力、位置编码、前馈网络等模块,大幅提升了模型表达能力与训练效率。从BERT到GPT系列,几乎所有现代大语言模型均基于Transformer构建,成为深度学习时代的关键技术突破之一。
266 7
|
19天前
|
人工智能 Cloud Native 中间件
划重点|云栖大会「AI 原生应用架构论坛」看点梳理
本场论坛将系统性阐述 AI 原生应用架构的新范式、演进趋势与技术突破,并分享来自真实生产环境下的一线实践经验与思考。
|
测试技术
开源按键组件MultiButton支持菜单操作(事件驱动型)
开源按键组件MultiButton支持菜单操作(事件驱动型)
827 1
开源按键组件MultiButton支持菜单操作(事件驱动型)