6. 线程池实现

news2024/12/25 23:51:10

WebServer::thread_pool() 方法用于创建并初始化线程池,为服务器的并发处理能力提供支持。在 Web 服务器中,线程池用于管理多个工作线程,这些线程负责处理客户端的 HTTP 请求,以确保服务器可以同时处理多个并发请求,而不需要为每个连接都创建一个新的线程。

/* 创建并初始化服务器的线程池 */
void WebServer::thread_pool()
{
    /* 输入参数: 并发模型,数据库连接池,线程池线程数 */
    m_pool = new threadpool<http_conn>(m_actormodel, m_connPool, m_thread_num);
} 

C++ 模板

在 C++ 中,template <typename T> 用于定义一个模板,其中typename T表示一个类型参数,可以在后续的代码中用具体的类型来替换。 模板是 C++ 中用于编写泛型可重用代码的重要特性。

模板函数

#include <iostream>
// 返回类型 函数名(参数列表);
template <typename T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << "整数相加:" << add(3, 4) << std::endl;
    std::cout << "浮点数相加:" << add(2.5, 4.5) << std::endl;
    return 0;
}

模板声明:template <typename T> 告诉编译器 T 是一个类型参数,占位符。

函数定义:T add(T a, T b) 定义了一个接受类型 T 的参数并返回类型 T 的函数。

函数调用: 编译器会根据传入的参数**自动推导**出类型 T

模板类

#include <iostream>

template <typename T>
class Pair {
public:
    Pair(T first, T second) : first_(first), second_(second) {}

    T getFirst() const { return first_; }
    T getSecond() const { return second_; }

private:
    T first_;
    T second_;
};

int main() {
    Pair<int> intPair(1, 2);
    std::cout << "第一个整数:" << intPair.getFirst() << ",第二个整数:" << intPair.getSecond() << std::endl;

    Pair<std::string> stringPair("你好", "世界");
    std::cout << "第一个字符串:" << stringPair.getFirst() << ",第二个字符串:" << stringPair.getSecond() << std::endl;

    return 0;
}

类的实例化: 在创建对象时指定实际的类型,例如 Pair<int>Pair<std::string>

常见的使用场景

标准模板库(STL): STL 广泛使用模板来实现容器(如 std::vectorstd::map)和算法(如 std::sortstd::find)。

泛型编程: 编写适用于任何类型的算法,只要这些类型满足一定的要求。

元编程: 使用模板在编译期间执行计算,提高运行时效率。

线程创建 pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
                        void *(*start_routine) (void *), void *arg);

pthread_create是 POSIX 线程库中的一个函数,用于创建一个新的线程。

  • thread:是一个输出参数,用于存储新创建线程的标识符
  • attr:用于指定新线程的属性,可以设置线程的栈大小、调度策略等。如果传入 NULL,则使用默认属性创建线程。
  • start_routine:是一个函数指针,指向新线程开始执行的函数。这个函数接收一个 void* 类型的参数,并返回一个 void* 类型的值。
  • arg:是传递给 start_routine 函数的参数。

如果成功创建线程,pthread_create 返回 0;否则,返回一个错误码。

创建线程后,可以使用pthread_join</font>等待线程结束

线程分离 pthread_detach

int pthread_detach(pthread_t thread);

pthread_detach用于将一个线程设置为分离状态(detached state),当一个线程被设置为分离状态后,当它结束时,其占用的系统资源会被自动回收,而不需要其他线程通过 pthread_join 来等待它并回收资源。

pthread_detachpthread_join 的区别

int pthread_join(pthread_t thread, void **retval);
int pthread_detach(pthread_t thread);

pthread_join 用于等待一个指定的线程终止,并获取该线程的返回值。如果线程 A 调用了 pthread_join 等待线程 B,那么线程 A 将被阻塞,直到线程 B 结束。当线程 B 结束后,线程 A 可以获取线程 B 的返回值(如果有)。

pthread_detach 用于将一个线程设置为“分离”状态,也就是说,该线程在结束时会自动释放它所占用的资源,而不需要通过 pthread_join 来显式回收。通常用于不需要与其他线程进行同步,也不关心该线程何时结束的场景。例如,一些后台任务或独立执行的子线程,创建后让其自行完成。

线程池主要功能

在这里插入图片描述

  • 面向多线程并发的任务处理机制 ;
  • 线程池创建: 创建thread_number 大小的线程池,实现资源复用, 减少了线程创建销毁的开销。
  • 任务请求队列std::list<T *> m_workqueue用于存放任务请求;
  • 使用互斥锁 (m_queuelocker) 来保证对任务队列的访问是线程安全的,以避免多个线程同时修改任务队列导致的数据竞争问题。
  • 工作线程从请求队列中取出任务并执行。线程池中使用了信号量 (m_queuestat) 来协调工作线程和任务的生产者之间的关系。 如果工作队列为空,则信号量为 0,工作线程阻塞等待。

改进

  1. 直接 delete[] m_threads 并不能完全清理所有线程相关的资源。m_threads 数组只是保存线程的标识符 (pthread_t) 信息,而这些线程的实际执行可能已经开始,或在创建过程中出现了部分成功部分失败的情况。delete[] m_threads 仅仅释放了存储这些标识符的数组,而没有释放线程的实际资源。 例如:在创建过程中,第 3 个线程创建失败,那么前 2 个线程已经成功创建并可能正在运行。在这种情况下,调用 delete[] m_threads,前 2 个成功创建的线程并没有被取消或者等待完成,因此这些线程所使用的系统资源没有被正确释放。这就会导致这些线程资源泄漏,成为僵尸线程。
    **改进:**当某个线程创建失败时,不仅释放线程标识符数组,同时销毁已经创建的线程。
for (int i = 0; i < thread_number; ++i)
    {
        /* 如果线程创建失败 */
        if (pthread_create(&threads[i], &attr, worker, this) != 0)
        {
            pthread_attr_destroy(&attr);                            /* 销毁线程属性对象 */
            
            for (int j = 0; j < i; ++j)
            {
                pthread_cancel(threads[j]);                         /* 取消已经创建的线程 */
            }
            throw std::exception();
        }
    }
  1. 线程池析构函数中同理,只释放了线程标识符数组,而不会处理线程池中正在运行的线程,会导致僵尸线程。
    改进:引入一个标志变量 m_stop,用于通知线程池中的线程停止工作。并清空请求队列
/* 工作线程的核心任务处理逻辑 */
template <typename T>
void threadpool<T>::run() {

    /* 当工作线程没有停止 */
    while (!m_stop)
        {
            // ...
        }
}

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

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

相关文章

基于Java的茶产品销售平台系统【附源码】

基于Java的茶产品销售平台系统 效果如下&#xff1a; 系统首页界面 用户登录界面 茶叶信息界面 在线客服界面 购物车界面 管理员登录界面 管理员功能界面 茶叶类型管理界面 研究背景 在当今社会&#xff0c;人们的生活节奏逐渐加快&#xff0c;人们对经济的要求逐渐降低&…

AI代币是什么?AI与Web3结合的未来方向在哪里?

近两年随着人工智能的崛起&#xff0c;AI已经渗透到制造业、电商、广告、医药等各个行业&#xff0c;加密货币领域也不例外&#xff0c;人工智能与区块链的融合&#xff0c;让我们看到了独特的数字资产 — AI加密代币。 它的流行始于2022年底&#xff0c;随着OpenAI智能聊天机…

Linux下MySQL8.x的编译安装与使用

Linux下MySQL的安装与配置 1. 安装环境初始化 1.1 查看是否安装过MySQL 如果使用rpm安装, 检查一下RPM PACKAGE rpm -qa | grep -i mysql # -i 忽略大小写 # 或者 yum list installed | grep mysql如果存在mysql-libs的旧版本包&#xff0c;显示如下 #存在 [rootlocalhost ~]…

如何在不安装WDK的情况下快速安装DevCon.exe?

你已经找到这里了&#xff0c;想必目的已经很清晰了&#xff0c;就是想要实现不安装WDK&#xff0c;又想使用Devcon.exe&#xff0c;那么往下看就对了。 这里直接上GitHub链接&#xff1a;https://github.com/Drawbackz/DevCon-Installer 考虑到网络环境&#xff0c;这里提供CS…

CSP/信奥赛C++刷题训练:经典二分例题(3):洛谷P8814[CSP-J 2022] 解密

CSP/信奥赛C++刷题训练:经典二分例题(3) [CSP-J 2022] 解密 题目描述 给定一个正整数 k k k,有 k k k 次询问,每次给定三个正整数 n i , e i , d i n_i, e_i, d_i ni​,ei​,di​,求两个正整数 p i , q i p_i, q_i pi​,qi​,使 n i = p i q i n_i = p_i \times…

git修改用户名与查看git的账号与密码

git修改用户名与查看git的账号与密码 文章目录 git修改用户名与查看git的账号与密码修改idea中代码提交的用户名查看git的账号与密码 修改idea中代码提交的用户名 1、打开您的IDEA&#xff0c;点击打开最下方的Terminal终端 2、输入以下命令&#xff0c;并回车执行 查看当前…

linux 安装php扩展:xlswriter

这里以xlswriter扩展为例 进入官方扩展&#xff1a;https://pecl.php.net查询自己php对应版本的扩展包 下载扩展 wget https://pecl.php.net/get/xlswriter-1.5.5.tgz 解压扩展 tar -zxvf xlswriter-1.5.5.tgz 进入扩展目录 cd xlswriter-1.5.5 查找对应php版本的phpiz…

解决电脑突然没有声音

问题描述&#xff1a;电脑突然没有声音了&#xff0c;最近没有怎么动过系统&#xff0c;没有安装或者卸载过什么软件&#xff0c;也没有安装或者卸载过驱动程序&#xff0c;怎么就没有声音了呢&#xff1f; 问题分析&#xff1a;仔细观察&#xff0c;虽然音量按钮那边看不到什…

php命令执行的一些执行函数----以ctfshow靶场为解题思路

PHP命令执行 一招鲜&#xff0c;吃遍天 cshow_source("flag.php"); cinclude($_GET[1]); cinclude("flag.php");var_dump(get_defined_vars()); web30&#xff1a; 这道题目过滤了flag,system,php。 那么我们 解法1&#xff1a;passthru ?cpassthru(…

mathorcup2024台风 我all in ai

三个问题&#xff0c;力大砖飞。 不建物理模型&#xff0c;直接all in好吧 第一个故意无监督 第二个LSTMCNN注意力&#xff0c;刚好时间空间 第三个在第二个上加了个transfomer &#xff0c;然后LSTM变双向&#xff0c;增加层数&#xff08;基线模型选的经验公式&#xff0c;少…

详细分析与梳理Java基础中的重点知识:String类 ,Java字符串String类入门,剖析String类底层机制

一、什么是String类&#xff1f; 众所周知&#xff0c;String类代表字符串类型。Java中所有被双引号包裹的字符串都是String类的对象。 &#xff08;比如&#xff1a;"zhangsan" , "lisi" , "博主是帅哥" , "123Abc"......&#xff0…

【C/C++】模拟实现strlen

学习目标&#xff1a; 使用代码模拟实现strlen。 逻辑&#xff1a; strlen 需要输入一个字符串数组类型的变量&#xff0c;并且返回一个整型类型的数据。strlen 需要计算字符串数组有多少个元素。 代码1&#xff1a;使用计数器 #define _CRT_SECURE_NO_WARNINGS 1 #include&…

Java面试经典 150 题.P55. 跳跃游戏(009)

本题来自&#xff1a;力扣-面试经典 150 题 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台https://leetcode.cn/studyplan/top-interview-150/ 题解&#xff1a; class Solution {public boolean canJump(int[] nums) {int…

梁山派入门指南2——滴答定时器位带操作按键输入

梁山派入门指南2——滴答定时器&位带操作&按键输入 1. 滴答定时器1.1 滴答定时器简介1.2 相关寄存器1.3 固件库函数 2. 位带操作2.1 位带操作介绍2.2 位带操作的优势2.3 支持位带操作的内存地址2.4 位带别名区地址的计算方式2.5 位带操作使用示例 3 按键输入3.1 独立按…

RHCE--4

第四章 web服务器 web服务器简介 www可以结合文字、图形、影像以及声音等多媒体&#xff0c;并通过可以让鼠标单击超链接的方式将信息以Internet传递到世界各处去。 www所用的协议&#xff1a;Hyper Text Transport Protocol&#xff0c;HTTP&#xff0c;超文本传输协议。 ww…

C++ | Leetcode C++题解之第515题在每个树行中找最大值

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> largestValues(TreeNode* root) {if (!root) {return {};}vector<int> res;queue<TreeNode*> q;q.push(root);while (!q.empty()) {int len q.size();int maxVal INT_MIN;while (…

如何安装和使用PowerDesigner

教程目录 一、安装二、使用 一、安装 1、启动安装程序。 2、Trial&#xff0c;然后Next。 3、选PRC&#xff0c;同意协议&#xff0c;Next。 4、设置安装路径&#xff0c;Next。 5、Next。 6、全选&#xff0c;Next。 7、Next。 8、Next。 9、等待安装。 10、…

人工智能生产力悖论:为什么大多数人没用上AI工具?

真正的障碍不是技术&#xff0c;而是思考的时间: 虽然像ChatGPT这样的工具确实有潜力带来变革&#xff0c;但我接触的大多数人几乎不用它。就算用的&#xff0c;也只是用来做些总结之类的小活儿。而在这些用户里&#xff0c;只有大约5%的人订阅了高级版&#xff0c;这意味着真…

JS中DOM和BOM

DOM DOM&#xff08;文档对象模型&#xff09;是一个跨平台和语言独立的接口&#xff0c;它允许程序和脚本动态地访问和更新文档的内容、结构和样式。在网页浏览器中&#xff0c;DOM 通常表示 HTML 或 XML 文档的对象模型。DOM 将网页内容视为节点树&#xff0c;其中每个节点都…

C语言初阶:十一.代码调试技巧

❤欢迎各位大佬访问&#xff1a;折枝寄北-CSDN博客折枝寄北擅长C语言初阶,等方面的知识,折枝寄北关注python,c,java,qt,c语言领域.https://blog.csdn.net/2303_80170533?typeblog❤文章所属专栏https://blog.csdn.net/2303_80170533/category_12794764.html?spm1001.2014.300…