[muduo网络库]——muduo库EventLoopThreadPool类(剖析muduo网络库核心部分、设计思想)

本文主要是介绍[muduo网络库]——muduo库EventLoopThreadPool类(剖析muduo网络库核心部分、设计思想),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接着之前我们[muduo网络库]——muduo库EventLoopThread类(剖析muduo网络库核心部分、设计思想),我们接下来继续看muduo库中的EventLoopThreadPool类,它和Thread以及EventLoopThread类息息相关。

EventLoopThreadPool类

事件循环线程池,管理所有客户端连接,每个线程都有唯一一个事件循环,可以调用setThreadNum设置线程的数目。线程池中每一个线程都有一个自己的EventLoop,而每一个EventLoop底层都是一个epoll,它利用了自身的epoll在没有事件的时候阻塞住,在有事件发生的时候,epoll监听到了事件就会去处理事件。

重要成员变量

EventLoop *baseLoop_;  //主线程loop
std::string name_;
bool started_; //标记当前状态 即IO线程是否开始运行
int numThreads_; //线程池中线程的数量
int next_;  //负载均衡用
std::vector<std::unique_ptr<EventLoopThread>> threads_;//创建事件的线程
std::vector<EventLoop*> loops_; //事件线程里面EventLoop的指针,每个EventLoopThread线程对应的EventLoop保存在loops_中
  • 具体含义如注释所示

重要成员函数

  • 设置底层线程的数量,状态,名字
void setThreadNum(int numThreads) { numThreads_ = numThreads;}
bool started() const { return started_;}
const std::string name() const { return name_;}
  • 启动线程池,实际上创建numThreads个线程,并让每个eventloopthread调用startLoop()
void EventLoopThreadPool::start(const ThreadInitCallback &cb)
{started_=true;for(int i=0; i<numThreads_; i++){char buf[name_.size() + 32];snprintf(buf,sizeof buf,"%s%d",name_.c_str(),i);EventLoopThread *t =new EventLoopThread(cb,buf);threads_.push_back(std::unique_ptr<EventLoopThread>(t)); //事件循环线程loops_.push_back(t->startLoop()); }//整个服务端只有一个线程,运行着baseloopif (numThreads_ == 0 && cb){cb(baseLoop_);//执行}
}
  1. 设置当前状态为true,根据需要的线程数numThreads_,创建线程
  2. 在for循环中,先创建一个EventLoopThread对象,构造线程池内线程集合
  3. 调用EventLoopThread::startLoop(),创建线程,绑定一个新的EventLoop,并返回loop地址,放入loops_中,loops_是一个std::vector<EventLoop*>类型,把每个EventLoopThread线程对应的EventLoop保存在loops_中。
  4. 如果没有其他线程,只有主线程的话,直接调用callback
  • 以轮询的方式分配channel给subloop
EventLoop* EventLoopThreadPool::getNextLoop()
{EventLoop* loop = baseLoop_;if(!loops_.empty())// 通过轮询,获取下一个处理事件的loop{loop = loops_[next_];++next_;if(next_ >= loops_.size()){next_ = 0;}}return loop;
}

注意: 在TcpServer::newConnection 会通过EventLoop *ioLoop = threadPool_->getNextLoop();初始时loop被赋值为baseLoop_,也就是主线程的loop,如果我们设置子线程为零的话程序也可正常运行,也就是说,getNextLoop的实现意味着muduo是支持单线程的;
如果loops_不为空,loop = loops_[next_],ioLoop就得到了一个subloop

花了很长时间在思考这个cb(baseLoop_)是为什么呢?(个人理解,如果大家觉得有错,麻烦指正)
  1. 在TcpServer::start(),启动IO线程池 threadPool_->start(threadInitCallback_); cb=threadInitCallback_;
  2. 来到了EventLoopThreadPool::start()中,创建一个EventLoopThread对象EventLoopThread *t =new EventLoopThread(cb,buf); ,在这里callback_(cb),先把cb给到了callback_
  3. 接着EventLoopThread::startLoop(),中调用 Thread::start()
  4. 在EventLoopThread的构造函数中,thread_(std::bind(&EventLoopThread::threadFunc,this),name),绑定了threadFunc,在Thread构造函数中func_(std::move(func)),所以会调用EventLoopThread::threadFunc()函数,这里创建了一个EventLoop,并给了callback_;
  5. 所以如果有其他线程,就创建一个loop给回去,没有就会给回去baseLoop_;
  6. EventLoopThreadPool里面的loops_就存了每个EventLoopThread线程对应的EventLoop;
  7. 然后loop_->runInLoop(std::bind(&Acceptor::listen,acceptor_.get()));

代码地址:https://github.com/Cheeron955/mymuduo/tree/master

好了~ 关于muduo库的EventLoopThreadPool类就剖析到这里,与它相关的Thread,EventLoopThread也都完结了,这部分其实有一点不知所云,希望大家发现错误能够批评指正。最后,除去TcpServer,我们就剩下InetAddress类了,下一篇我们来剖析InetAddress类,然后就从整个服务器流程来讲TcpServer ~ 我们下一节见 ~~

这篇关于[muduo网络库]——muduo库EventLoopThreadPool类(剖析muduo网络库核心部分、设计思想)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991391

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

Linux find 命令完全指南及核心用法

《Linuxfind命令完全指南及核心用法》find是Linux系统最强大的文件搜索工具,支持嵌套遍历、条件筛选、执行动作,下面给大家介绍Linuxfind命令完全指南,感兴趣的朋友一起看看吧... 目录一、基础搜索模式1. 按文件名搜索(精确/模糊匹配)2. 排除指定目录/文件二、根据文件类型筛选三、时间

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

Python中的可视化设计与UI界面实现

《Python中的可视化设计与UI界面实现》本文介绍了如何使用Python创建用户界面(UI),包括使用Tkinter、PyQt、Kivy等库进行基本窗口、动态图表和动画效果的实现,通过示例代码,展示... 目录从像素到界面:python带你玩转UI设计示例:使用Tkinter创建一个简单的窗口绘图魔法:用

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如