【C++ 面向对象编程】补档:线程池和 MySQL 连接池的设计模式分析

文章目录

推荐一个零声教育学习教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习: https://github.com/0voice 链接

前言

我之前写过一篇文章,是介绍 C++ 设计模式的,原文链接 在此。本篇文章小试牛刀,尝试分析之前写过的线程池和 MySQL 连接池的设计,各自的原文链接分别是 手撕 C++ 线程池手撕 MySQL 连接池

线程池的设计模式分析

还是给出那个思考步骤。

设计模式 = 使用场景 + 面向接口编程 + 稳定点 / 不稳点分析 设计模式 = 使用场景 + 面向接口编程 + 稳定点/不稳点分析 设计模式=使用场景+面向接口编程+稳定点/不稳点分析

应用场景:

1、线程池有若干个工作线程,这些工作线程是可以复用的。

2、当无任务推送过来的时候,线程处于休眠状态,不占用计算机资源。

3、当所有工作线程都在工作的时候,还需要把一路推送过来的任务储存起来。

应该解决的问题
稳定点 :即依赖关系。线程主动在其所在的线程池内寻找任务。线程主动执行任务。任务都是同一类型的。
不稳定点:一对多的对应关系。一个线程池有任意多个任务,同时也可以有任意多个线程。

我们发现有三个角色的三角关系要处理,线程池、线程、任务。接下来用面向接口编程的思维去思考。

解决稳定点 (里氏替换原则、单一职责原则、最小知道原则)

1、线程已有现成的架构,无需我们去多想,构造线程的时候,就已经同时运行其任务函数了。

2、线程池应该提供一个接口,这个接口就是工作线程的任务调度函数,让其按时机执行任务。

解决不稳定点 (接口隔离原则 (ISP)、开放封闭原则 (OCP)、依赖倒置原则 (DIP))

1、线程池体内组合线程成员接口,线程按照 vector 容器组织起来。线程执行的任务调度函数来自线程池。

2、线程池体内组合任务队列接口,组织任务的是 "拥塞队列",并且还要提供 post 任务的接口。

3、拥塞队列应该有,push、pop、cancel 三个接口,一个是推送、取出任务,销毁线程池。除此之外,还要准备同步原语,保证任务队列的线程安全。在原文,我是把它设计成双交换队列,提高其任务吞吐量。

结合起来说:

1、线程池与线程之间是观察者模型。线程池是一个被观察的对象,而线程是观察线程池的观察者,具体来说是观察线程池里的任务拥塞队列。

2、线程池与任务拥塞队列之间是代理关系,线程池的 post 接口代理了拥塞队列的 push 接口。

经过分析,归纳成如下图

首先是线程池


之后是拥塞队列


整体架构如下


MySQL 连接池的设计模式分析

还是给出那个思考步骤。

设计模式 = 使用场景 + 面向接口编程 + 稳定点 / 不稳点分析 设计模式 = 使用场景 + 面向接口编程 + 稳定点/不稳点分析 设计模式=使用场景+面向接口编程+稳定点/不稳点分析

应用场景:

1、MySQL 连接池有若干个 MySQL 的连接,对应多个工作线程处理该连接。

2、当无任务 SQL 语句要执行的时候,线程处于休眠状态,不占用计算机资源。.

3、当所有工作线程都在工作的时候,还需要把一路推送过来的任务 SQL 储存起来。

4、可对 SQL 查询的结果进行某种数据处理。

应该解决的问题
稳定点 :即依赖关系。线程主动在其所在的连接池池内寻找任务。线程主动执行任务 SQL。任务 SQL 都是同一类型的,查询的结果都是同一类型的。
不稳定点:一对多的对应关系。一个 MySQL 连接池有任意多个任务 SQL(当然也是有对应多个查询结果)、连接任意多个数据库数据表,同时也可以有任意多个线程与对应多个的 MySQL 连接。数据处理器可以处理任意多个数据任务。

我们发现有四个角色的四角关系要处理,连接池、线程/连接、任务 SQL、数据处理器。接下来用面向接口编程的思维去思考。

  • MySQL 连接池

    解决稳定点:

    ------1、提供连接池资源配置接口,

    ------2、提供外界输入 SQL 语句的接口(同时代理 sql 语句拥塞队列的 push 接口)

    解决不稳定点:(组合优于继承,开闭原则)

    ------1、使用 vector 容器包纳 mysql连接 和 对应线程(还需要提供任务调度函数接口)

    ------2、使用 sql 任务语句拥塞队列容器包纳 sql 查询任务(提供 pop、push 接口)

    ------3、使用 vector 容器包纳多个数据库的信息

    ------4、连接/线程 的调度函数接口会主动的操作拥塞队列,从中取出 sql 语句去执行

    ------5、使用 vector 容器包纳多个 mysql 查询结果接口

  • 优化组合1,连接池工作者 MySQLWorker

    ------1、把线程接口和 MySQL 连接接口组合起来,并且可以同时观察 SQL 语句拥塞队列(拥有其指针)

    ------2、提供 SQL 语句调度函数,是可以去拥塞队列里面 pop 出 sql 语句

  • 优化组合2,连接接口 MySQLConn

    ------1、组合接口 MySQLWorker 和连接配置信息 sql::Connection

    ------2、提供数据库查询接口 Query

  • MySQLWorker 补充组合

    ------1、MySQLWorker 补充接口 MySQLConn

  • 优化组合4,SQLOperation 查询操作

    ------1、把官方库的查询结果接口、sql 语句字符串组合起来

    ------2、提供 sql 语句的执行接口 Excute (worker 执行)和对外通信接口 GetFuture(处理器获取)

    ------3、把拥塞队列的内容变成 SQLOperation

  • 异步处理器

    解决稳定点:

    ------1、提供外界投放数据回调处理任务的接口。

    ------2、投放任务的时候,必须包含处理函数与其传入参数。

    ------3、如果这个传入参数一时间不能获得,那就给他一个期权 future。

    解决不稳定点:

    ------1、回调处理任务是可以任意多个的。使用 vector 容器包纳多个数据处理任务函数、传入参数。

    ------2、由于传入了许多参数位置的处理任务,需要等待传入的参数很多,故而需要提供一个轮询接口。

  • 回调处理函数的组合优化,QueryCallback

    ------1、期权 future 参数接口与回调处理函数组合在一起。

    ------2、提供对期权 future 参数的就绪查询接口(被异步处理器调用)

综上所述,我们可以做出 MySQL 的架构图


这么看下来

1、连接池是被观察的对象,观察者就是 MySQLConn 或者 MySQLWorker

2、连接池代理了 SQLOperation 接口

3、SQLOperation 推送了期权 future 参数给处理器(还有对应的处理函数),这样说来连接池和异步处理器是观察者模式。

相关推荐
念何架构之路14 分钟前
Go进阶之panic
开发语言·后端·golang
亓才孓18 分钟前
[Properties]写配置文件前,必须初始化Properties(引用变量没执行有效对象,调用方法会报空指针错误)
开发语言·python
洛豳枭薰18 分钟前
Innodb一次更新动作
mysql
傻乐u兔21 分钟前
C语言进阶————指针3
c语言·开发语言
两点王爷31 分钟前
Java基础面试题——【Java语言特性】
java·开发语言
Swift社区39 分钟前
Gunicorn 与 Uvicorn 部署 Python 后端详解
开发语言·python·gunicorn
码农阿豪1 小时前
Python Flask应用中文件处理与异常处理的实践指南
开发语言·python·flask
岁岁种桃花儿1 小时前
CentOS7 彻底卸载所有JDK/JRE + 重新安装JDK8(实操完整版,解决kafka/jps报错)
java·开发语言·kafka
xcLeigh1 小时前
Python 项目实战:用 Flask 实现 MySQL 数据库增删改查 API
数据库·python·mysql·flask·教程·python3
rainbow68891 小时前
Linux文件描述符与重定向原理
c++