基于多反应堆的高并发服务器【C/C++/Reactor】(中)线程池的启动和从线程池中取出一个反应堆实例

一、线程池的启动 (主线程)

// 启动线程池 (主线程)
void threadPoolRun(struct ThreadPool* pool) {
    /*
        线程池被创建出来之后,接下来就需要让线程池运行起来,
        其实就是让线程池里的若干个子线程运行起来
    */
    // 确保线程池未运行  
    assert(pool && !pool->isStart);
    // 比较主线程的ID和当前线程ID是否相等 
    // 相等=>确保执行线程为主线程;不相等=>exit(0)
    if(pool->mainLoop->threadID != pthread_self()) {
        exit(0);
    }
    pool->isStart = true; // 标记为启动
    if(pool->threadNum > 0) { // 线程数量大于零
        for(int i=0;i<pool->threadNum;++i) {
            workerThreadInit(&pool->workerThreads[i], i);// 初始化子线程
            workerThreadRun(&pool->workerThreads[i]); // 启动子线程
        }
    }
}

## 学习笔记:线程池的运行机制

  • 线程池被创建后,需要启动使其子线程运行。启动线程池的函数需要一个有效struct ThreadPool*类型指针pool作为参数,和threadNum代表子线程总个数
// 初始化线程池
struct ThreadPool* threadPoolInit(struct EventLoop* mainLoop, int threadNum);
  • 确保线程池未运行且执行线程为主线程
// 确保线程池未运行
assert(pool && !pool->isStart);
// 比较主线程的ID和当前线程ID是否相等 
// 相等=>确保执行线程为主线程;不相等=>exit(0)
if(pool->mainLoop->threadID != pthread_self()) {
    exit(0);
}

如果条件满足,将线程池标记为已启动,并初始化并启动子线程;如果线程数量大于零,通过WorkerThread模块的workerThreadInit函数进行初始化,通过WorkerThread模块的workerThreadRun函数进行启动;如果线程数量为零,线程池可以提供主线程的反应堆模型(mainLoop)

pool->isStart = true; // 标记为启动
if(pool->threadNum > 0) { // 线程数量大于零
    for(int i=0;i<pool->threadNum;++i) {
        workerThreadInit(&pool->workerThreads[i], i);// 初始化子线程
        workerThreadRun(&pool->workerThreads[i]); // 启动子线程
    }
}

### 知识点:线程池的启动

  • 启动线程池的函数需要确保传入的结构体指针有效且线程池未运行
  • 执行线程需要判断是否为主线程,避免异常情况
  • 成功启动后,需要初始化并启动子线程,通过WorkerThread模块的函数进行初始化和启动
  • 如果线程数量为零,线程池可以提供主线程的反应堆模型(mainLoop) 

二、从线程池中取出一个反应堆实例 (主线程)

此外,takeWorkerEventLoop函数 主线程可以从线程池中取出某个子线程的反应堆实例。

目的:这个函数是主线程调用的,因为主线程是拥有线程池的。因此主线程可以遍历线程池里边的子线程,从中挑选一个子线程,得到它的反应堆模型,再将处理的任务放到反应堆模型里边。

// 取出线程池中的某个子线程的反应堆实例
struct EventLoop* takeWorkerEventLoop(struct ThreadPool* pool) {
    assert(pool->isStart);// 确保线程池是运行的
    // 比较主线程的ID和当前线程ID是否相等 
    // 相等=>确保执行线程为主线程;不相等=>exit(0)
    if(pool->mainLoop->threadID != pthread_self()) {
        exit(0);
    }
    // 从线程池中找到一个子线程,然后取出里边的反应堆实例
    struct EventLoop* evLoop = pool->mainLoop; 
    if(pool->threadNum > 0) {
        evLoop = pool->workerThreads[pool->index].evLoop;
        pool->index = ++pool->index % pool->threadNum;
    }
    return evLoop;
}

如果线程数量为零,evLoop 为主线程的反应堆模型(mainLoop),即:

evLoop=pool->mainLoop;

如果线程数量大于零,从线程池中的某个子线程获取其事件循环,并将其存储在evLoop变量中。为了对线程池中的工作线程实现雨露均沾,故需要用到index这个变量,为了确保 pool->index  的值在合适的取值范围内并且不会超出它的取值范围:先将 pool->index  的值加一,然后对 pool->threadNum取余数,并将结果赋值给 pool->index :

① pool->index++;② pool->index %= pool->threadNum;

=>③ pool->index = ++pool->index % pool->threadNum;

if(pool->threadNum > 0) {
    evLoop = pool->workerThreads[pool->index].evLoop;
    pool->index = ++pool->index % pool->threadNum;
}

 ### 知识点:子线程的反应堆实例的取出

  • 可以通过takeWorkerEventLoop函数从线程池中取出子线程的反应堆实例
  • 这个函数的核心是取出反应堆实例,用于处理任务
  • 如果线程数量为零,evLoop 为主线程的反应堆模型(mainLoop)
  • 对线程池中的工作线程实现雨露均沾地分配各个子线程调度,避免所有任务都由同一个线程处理,还确保index在合适的取值范围

>>总结:

        本文主要讲述了线程池的启动过程和操作函数。在启动线程池时,需要传入有效指针,确保线程池未被运行,并判断执行线程的线程是否为主线程。通过WorkerThread模块中的函数对子线程进行初始化并启动。主线程可以方便地管理子线程,并从中选择一个子线程以获取其反应堆模型。

        此外,还讲述了线程池操作的函数,包括初始化、启动和取出子线程等。整个处理流程需要确保每个任务都能被雨露均沾地分配给各个子线程,避免所有任务都由同一个线程处理,还确保了index在合适的取值范围。

>>线程池总结:

// 初始化线程池
struct ThreadPool* threadPoolInit(struct EventLoop* mainLoop, int threadNum);

// 启动线程池 
void threadPoolRun(struct ThreadPool* pool);

// 取出线程池中的某个子线程的反应堆实例
struct EventLoop* takeWorkerEventLoop(struct ThreadPool* pool);

threadPoolInit函数、threadPoolRun函数、takeWorkerEventLoop函数都需要在主线程里边进行依次调用。首先调用threadPoolInit函数得到pool实例,之后调用threadPoolRun函数启动线程池(意味着里边的子线程会启动)。接着调用takeWorkerEventLoop函数取出线程池中的某个子线程的反应堆实例,再把这个实例给到调用者,调用者就可以通过这个实例,往它的任务队列里边添加任务,这个任务添加到evLoop的任务队列里边去了之后,就开始处理任务队列。然后再根据任务队列里边的节点类型来处理Dispatcher的检测集合。有三种情况:

  • 情况1.往检测集合里边添加新的节点
  • 情况2.从检测集合里边删除一个节点
  • 情况3.修改检测集合里边某个文件描述符对应的事件

Dispatcher这个检测集合被处理完之后,这个反应堆模型开始进行一个循环,它需要循环调用底层的poll/epoll_wait/select函数来检测这个集合里边是否有激活的文件描述符。如果有激活的文件描述符,那么就通过这个文件描述符找到它所对应的channel。找到这个channel之后,再基于激活的事件调用事件对应的回调函数。这个函数调用完成之后,对应的事件也就处理完毕。这就走完了整个的处理流程

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JVM虚拟机的垃圾回收器(面试题)

1.什么是垃圾回收 垃圾回收主要说的是java会自动把程序在运行过程中产生的一些没有用的对象给回收掉&#xff0c;这样可以避免内存的浪费。 java主要是通过一个叫“根可达”的算法来识别这个对象是否可以被回收的&#xff0c;然后回收的算法也主要有三种&#xff1a;标记清除&a…

Python 教程 02:Python 编程环境的搭建与 IDE 的选择

目录 一、搭建 Python 环境 1.1 Python 官网 1.2 下载 Python 1.2.1 选择版本 1.2.2 选择平台 1.2.3 下载安装文件&#xff08;Windows & macOS&#xff09; 1.3 安装环境 1.3.1 Windows 平台 1.3.2 macOS 平台 1.3.3 Linux 平台 1.4 验证安装是否成功 二、选择…

Flink自定义Source模拟数据流

maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

瓢虫目标检测数据集VOC格式400张

瓢虫&#xff0c;一种小巧玲珑、色彩鲜艳的昆虫&#xff0c;因其独特的形态和生态习性而受到广泛欢迎。 瓢虫的体型小巧&#xff0c;一般为圆球形&#xff0c;体色鲜艳&#xff0c;有红、黄、黑等多种颜色。它们通常有一个坚硬的外壳&#xff0c;可以保护自己不受天敌的侵害。…

12月笔记

#pragma once 防止多次引用头文件&#xff0c;保证同一个&#xff08;物理意义上&#xff09;文件被多次包含&#xff0c;内容相同的两个文件同样会被包含。 头文件.h与无.h的文件&#xff1a; iostream是C的头文件&#xff0c;iostream.h是C的头文件&#xff0c;即标准的C头文…

前端--基础 常用标签 - 超链接标签 ( 内部链接,空链接,下载链接,网页元素连接)

链接分类 &#xff1a; 外部链接 内部链接 空链接 下载链接 网页元素链接 内部链接 &#xff1a; 即 网站内部页面之间的相互链接&#xff0c;直接点击 链接内部页面名称即可 所谓内部链接&#xff0c;就是在同一个网站里面&#xff0c;有许多链接&#xff0c;当你在 a…

机器学习笔记 - 用于语义图像分割的空洞卷积DeepLabv3

一、什么是DeepLabv3&#xff1f; DeepLabv3 是用于语义分割任务的深度神经网络 (DNN) 架构。虽然不是比较新的网络模型&#xff0c;但是也是分割模型里的杰出代表之一&#xff0c;所以还是值得深入了解。 它使用Atrous&#xff08;Dilated&#xff09;卷积来控制感受野和特征图…

房贷计算器,妥妥的数学计算

根据给出的公式&#xff0c;编写房贷计算器。妥妥的数学计算&#xff0c;把数学公式“翻译”成代码就好。 (笔记模板由python脚本于2024年01月06日 18:08:55创建&#xff0c;本篇笔记适合初具基本编程能力的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;http…

服务器GPU温度过高挂掉排查记录

服务器GPU挂掉 跑深度学习的代码的时候发现中断了。通过命令查看&#xff1a; nvidia-smi显示 Unable to determine the device handle for GPU 0000:01:00.0: Unknown Error。感觉很莫名其妙。通过重启大法之后&#xff0c;又能用一段时间。 shutdown -r now但是过了一个小…

遗传算法(GA)、模拟退火算法(SAA)、蚁群算法(ACO)、粒子群算法(PSO)优缺点汇总

遗传算法 优点&#xff1a; 与问题领域无关且快速随机的搜索能力&#xff0c;不会陷入局部最优解&#xff1b;搜索从群体出发&#xff0c;具有潜在的并行性&#xff0c;提高运行速度&#xff0c;鲁棒性高&#xff1b;搜索使用评价函数启发&#xff0c;过程简单&#xff1b;使…

基于Java实现全功能电子商城

&#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩项目推荐订阅&#x1f447;&#x1f3fb; 不然下次找不到哟 基于SpringBoot的旅游网站 基于SpringBoot的MusiQ音乐网站 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及…

小游戏实战丨基于PyGame的俄罗斯方块小游戏

文章目录 写在前面PyGame五子棋注意事项系列文章写在后面 写在前面 本期内容&#xff1a;基于pygame的俄罗斯方块小游戏 下载地址&#xff1a;https://download.csdn.net/download/m0_68111267/88700182 实验环境 python3.11及以上pycharmtkinter PyGame Pygame是一个非常…

Java设计模式-模板方法模式

目录 一、豆浆制作问题 二、模板方法模式基本介绍 三、原理类图 四、模板方法模式解决豆浆制作问题 五、模板方法模式的钩子方法 六、模板方法模式在Spring框架应用的源码分析 七、注意事项和细节 一、豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下 : 1) 制作…

案例098:基于微信小程序的电子购物系统的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【大数据进阶第三阶段之Datax学习笔记】使用阿里云开源离线同步工具DataX 实现数据同步

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使用…

RH850P1X芯片学习笔记-A/D Converter (ADCF)

文章目录 Features of RH850/P1x-C ADCFNumber of UnitsRegister Base AddressClock SupplyInterrupts and DMAHardware ResetExternal Input/Output SignalsVirtual Channel OverviewFunctional OverviewBlock DiagramPhysical Channels, Virtual Channels and Scan Groups Re…

SPRING BOOT发送邮件验证码(Gmail邮箱)

SPRING BOOT邮件发送验证码 一、Gmail邮箱配置 1、进入Gmail(https://mail.google.com) 2、打开谷歌右上角设置 3、启用POP/IMP 4、启用两步验证(https://myaccount.google.com/security) 5、建立应用程式密码 6、复制保存应用程式密码 二、代码 1、引入依赖 <d…

【LMM 012】TinyGPT-V:24G显存训练,8G显存推理的高效多模态大模型

论文标题&#xff1a;TinyGPT-V: Efficient Multimodal Large Language Model via Small Backbones 论文作者&#xff1a;Zhengqing Yuan, Zhaoxu Li, Lichao Sun 作者单位&#xff1a;Anhui Polytechnic University, Nanyang Technological University, Lehigh University 论文…

Window端口占用处理

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

C#编程-实现函数重载

考虑一个示例&#xff1a;您必须编写一个程序来实现计算器的功能。计算器执行各种运算&#xff0c;例如数字的加、减及乘等。可以对任何类型的数据执行这些运算。这是否意味着您必须定义单独的函数名&#xff08;如addInteger、addFloat和addDoublie&#xff09;对每种此类数字…