Webserver(5.3)线程池实现

目录

  • 线程池
  • locker.h
  • threadpool.h

线程池

相比于动态地创建子线程,选择一个已经存在的子线程的代价显然要小得多。至于主线程选择哪个子线程来为新任务服务,有多种方式:

  • 主线程使用某种算法来主动选择子线程。最简单、最常用的算法是随机算法和Round Robin(轮流选取)算法,但更优秀、更智能的算法将使任务在各个工作线程中更均匀地分配,从而减轻服务器的整体压力。
  • 主线程和所有子线程通过一个共享的工作队列来同步,子线程都睡眠在该工作队列上。当有新的任务到来时,主线程将任务添加到工作队列中。这将唤醒正在等待任务的子线程,不过只有一个子线程将获得新任务的“接管权”,它可以从工作队列中取出任务并执行之,而其他子线程将继续睡眠在工作队列上。

线程间竞争的不是CPU的计算资源而是IO,IO的处理一般较慢。
池是一组资源的集合,这组资源在服务器启动之初就被完全创建好并初始化,这称为静态资源。
当服务器执行完之后,把相关的资源放回池中,无需执行系统调用释放资源。
创建一个webserver目录
在这里插入图片描述

locker.h

#ifndef LOCKER_H
#define LOCKER_H

#include<pthread.h>
#include<exception>
#include<semaphore.h>

//线程同步机制封装类

//互斥锁类
class locker{
public:
    locker(){
        if(pthread_mutex_init(&m_mutex,NULL)!=0){
            throw std::exception();
        }
    }

    ~locker(){
        pthread_mutex_destroy(&m_mutex);
    }

    bool lock(){
        return pthread_mutex_lock(&m_mutex)==0;
    }

    bool unlock(){
        return pthread_mutex_unlock(&m_mutex)==0;
    }

    pthread_mutex_t * get(){
        return &m_mutex;
    }
private:
    pthread_mutex_t m_mutex;
};

//条件变量类
class cond{
public:
    cond(){
        if(pthread_cond_init(&m_cond,NULL)!=0){
            throw std::exception();
        }
    }

    ~cond(){
        pthread_cond_destroy(&m_cond);
    }

    bool wait(pthread_mutex_t * mutex){
        return pthread_cond_wait(&m_cond,mutex)==0;
    }

    bool timewait(pthread_mutex_t * mutex,struct timespec t){
        return pthread_cond_timedwait(&m_cond,mutex,&t)==0;
    }

    bool signal(){
        return pthread_cond_signal(&m_cond)==0;
    }

    bool broadcast(){
        return pthread_cond_broadcast(&m_cond)==0;
    }
private:
    pthread_cond_t m_cond;
};

//信号量类
class sem{
public:
    sem(){
        if(sem_init(&m_sem,0,0)!=0){
            throw std::exception();
        }
    }

    sem(int num){
        if(sem_init(&m_sem,0,num)!=0){
            throw std::exception();
        }
    }

    ~sem(){
        sem_destroy(&m_sem);
    }

    //等待信号量
    bool wait(){
        return sem_wait(&m_sem)==0;
    }

    //增加信号量
    bool post(){
        return sem_post(&m_sem)==0;
    }
private:
    sem_t m_sem;
};
#endif

threadpool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include<pthread.h>
#include<list>
#include<exception>
#include<cstdio>
#include"locker.h"

//线程池类,定义成模板类是为了代码的复用,模板参数T是任务类
template<typename T>
class threadpool{
public:
    threadpool(int thread_number=8,int max_requests=10000);
    ~threadpool();
    bool append(T* request);

private:
    static void* worker(void * arg);
    void run();

private:
    //线程的数量
    int m_thread_number;

    //线程池数组,大小为m_thread_number
    pthread_t * m_threads;

    //请求队列中最多允许的,等待处理的请求数量
    int m_max_requests;

    //请求队列
    std::list< T*> m_workqueue;

    //互斥锁
    locker m_queuelocker;

    //信号量用来判断是否有任务需要处理
    sem m_queuestat;

    //是否结束线程
    bool m_stop;
};

template<typename T>
threadpool<T>::threadpool(int thread_number,int max_requests) :
    m_thread_number(thread_number),m_max_requests(max_requests),
    m_stop(false),m_threads(NULL){

    if((thread_number <=0)||(max_requests<=0)){
        throw std::exception();
    }

    m_threads=new pthread_t[m_thread_number];
    if(!m_threads){
        throw std::exception();
    }

    //创建thread_number个线程,并将它们设置为线程脱离
    for(int i=0;i<thread_number;i++){
        printf("create the %dth thread\n",i);

        if(pthread_create(m_threads + i,NULL,worker,this)!=0){
            delete [] m_threads;
            throw std::exception();
        }

        if(pthread_detach(m_threads[i])){
            delete[] m_threads;
            throw std::exception();
        }
    }
    }

template<typename T>
threadpool<T>::~threadpool(){
    delete[] m_threads;
    m_stop=true;
}

template<typename T>
bool threadpool<T>::append(T *request){
    m_queuelocker.lock();
    if(m_workqueue.size()>m_max_requests){
        m_queuelocker.unlock();
        return false;
    }

    m_workqueue.push_back(request);
    m_queuelocker.unlock();
    m_queuestat.post();
    return true;
}

template<typename T>
void* threadpool<T>::worker(void *arg){

    threadpool * pool=(threadpool *)arg;
    pool->run();
    return pool;
}

template<typename T>
void threadpool<T>::run(){
    while(!m_stop){
        m_queuestat.wait();
        m_queuelocker.lock();
        if(m_workqueue.empty()){
            m_queuelocker.unlock();
            continue;
        } 
        T* request=m_workqueue.front();
        m_workqueue.pop_front();
        m_queuelocker.unlock();

        if(!request){
            continue;
        }
        request->process();
    }
}
#endif

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

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

相关文章

解决:使用EasyExcel导入Excel模板时出现数据导入不进去的问题

解决&#xff1a;使用EasyExcel导入Excel模板时出现数据导入不进去的问题 在Java中&#xff0c;当我们用EasyExcel导入Excel时&#xff0c;可能会出现数据导入不进去的问题。例如&#xff1a; 这种异常等。 问题原因1&#xff1a;这个1代表从第几行开始&#xff0c;你的exce…

可视化建模与UML《类图实验报告》

史铁生&#xff1a; 余华和莫言扛着我上火车&#xff0c; 推着走打雪仗&#xff0c; 还带我偷西瓜&#xff0c; 被人发现后他们拔腿就跑&#xff0c; 却忘了我还在西瓜地里。 一、实验目的&#xff1a; 1、熟悉类图的构件事物。 2、熟悉类之间的泛化、依赖、聚合和组合关系…

python(自用查看版)

目录 1.注意事项 1.1 python的除法不是整除&#xff0c;得到的是浮点数 1.2算术符号基于数学的算术优先级。具体可自行查看。 1.3注释 1.4缩进 1.5换行 1.6常见关键字 1.7续行符 1.8报错 1.9赋值 1.10比较运算符 2.常量和表达式 3.变量 4.数据类型 4.1整型int …

TMDOG的Gin学习笔记_02——Gin集成支付宝支付沙箱环境

TMDOG的Gin学习笔记_02——Gin集成支付宝支付沙箱环境 博客地址&#xff1a;TMDOG的博客 作者自述&#xff1a; 最近忙着整理自己的项目代码&#xff0c;终于有时间更新一下博客。这次的内容是关于如何在Gin框架下集成支付宝的支付沙箱环境&#xff0c;具体包括如何初始化支付…

cmake could not find a package configuration file provided by “Microsoft.GSL“

通过查找 dir C:\vcpkg\installed\x64-windows /s /b | findstr Microsoft.GSL vspkg安装 git clone https://github.com/microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat .\vcpkg --version

cocos creator 3.8.3物理组件分组的坑

坑&#xff0c;坑的不行的大坑 group用的二进制的左移获取十进制的数值 目前是这样判断的&#xff0c;也不知道对不对&#xff0c;什么get、set Group没找到

【AI写作宝-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

计算机毕业设计Python流量检测可视化 DDos攻击流量检测与可视化分析 SDN web渗透测试系统 网络安全 信息安全 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

2024.11最新Hexo+GitHub搭建个人博客

2024.11最新HexoGitHub搭建个人博客 一、Hexo介绍 Hexo 是一个快速、简洁且高效的博客框架&#xff0c;有丰富的主题和插件可供使用。 Hexo 使用 Markdown&#xff08;或其他标记语言&#xff09;解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。这…

王道考研之数据结构

数据结构系列 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 数据结构 数据结构系列1.线性表1.1 线性表的定义和相关概念1.2 线性表的创销 增删查改 判空表长打印 2.顺序表2.1 顺序表定义和相关概念2.2 顺序表的静态实现2.3 顺序表的…

java导出word文件(手绘)

文章目录 代码细节效果图参考资料 代码细节 使用的hutool的WordUtil&#xff0c;WordUtil对poi进行封装&#xff0c;但是这一块的官方封装的很少&#xff0c;很多细节都没有。代码中是常见的绘制段落&#xff0c;标题、表格等常用api Word07Writer writer WordUtil.getWriter(…

LeetCode 0685.冗余连接 II:并查集(和I有何不同分析)——详细题解(附图)

【LetMeFly】685.冗余连接 II&#xff1a;并查集&#xff08;和I有何不同分析&#xff09;——详细题解(附图) 力扣题目链接&#xff1a;https://leetcode.cn/problems/redundant-connection-ii/ 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&…

git原理与上传

言&#xff1a; git是一个软件&#xff0c;gitee/github是一个网站&#xff0c;这里有什么联系吗&#xff1f;我们身为一个程序员不可能不知道github&#xff0c;但是毕竟这是外国的网站&#xff0c;我们不翻墙的情况下&#xff0c;是无法访问的(或者就是太慢了&#xff0c;或…

Go语言的常用内置函数

文章目录 一、Strings包字符串处理包定义Strings包的基本用法Strconv包中常用函数 二、Time包三、Math包math包概述使用math包 四、随机数包&#xff08;rand&#xff09; 一、Strings包 字符串处理包定义 Strings包简介&#xff1a; 一般编程语言包含的字符串处理库功能区别…

React 入门课程 - 使用CDN编程React

1. 第一个React 注意&#xff1a;在vscode里&#xff0c;使用Live Server来运行html文件。 index.html <html><head><link rel"stylesheet" href"index.css"><script crossorigin src"https://unpkg.com/react17/umd/react.de…

苍穹外卖day09超出配送范围前端不提示问题

同学们在写苍穹外卖项目day09时调用了百度地图api来判断用户地址是否超出配送范围&#xff0c; 但是在黑马官方的课程或资料中&#xff0c;出现这样的问题时只会向用户端的控制台报错并不会提醒用户 如下图&#xff1a; 解决方法&#xff1a; 其实解决方法很简单只需要找到向…

ARXML汽车可扩展标记性语言规范讲解

ARXML: Automotive Extensible Markup Language &#xff08;汽车可扩展标记语言&#xff09; xmlns: Xml name space &#xff08;xml 命名空间&#xff09; xsd: Xml Schema Definition (xml 架构定义) 1、XML与HTML的区别&#xff0c;可扩展。 可扩展&#xff0c;主要是…

【开源项目】经典开源项目数字孪生智慧小镇——开源工程及源码

飞渡科技数字孪生小镇管理平台&#xff0c;依托自研数字孪生引擎平台&#xff0c;将5G、物联网、大数据、人工智能等数字化技术融合应用&#xff0c;采集、整合、应用小镇的规划、运营、管理等数据&#xff0c;实现特色小镇全域管理系统化以及精细化。 基于地理信息系统&#x…

探索 Move 编程语言:智能合约开发的新纪元

目录 引言 一、变量的定义 二、整型 如何在Move中表示小数和负数&#xff1f; 三、运算符 as运算符 布尔型 地址类型 四、什么是包&#xff1f; 五、什么是模块&#xff1f; 六、如何定义方法&#xff1f; 方法访问权限控制 init方法 总结 引言 Move 是一种专为区…

智能提醒助理系列-jdk8升级到21,springboot2.3升级到3.3

本系列文章记录“智能提醒助理”产品建设历程&#xff0c;记录实践经验、巩固知识点、锻炼总结能力。 本篇介绍技术栈升级的过程&#xff0c;遇到的问题和解决方案。 一、需求出发点 智能提醒小程序 当前使用的是jdk8&#xff0c;springboot2.3,升级到jdk21和springboot3.3 学…