【线程】线程池

线程池通过一个线程安全的阻塞任务队列加上一个或一个以上的线程实现,线程池中的线程可以从阻塞队列中获取任务进行任务处理,当线程都处于繁忙状态时可以将任务加入阻塞队列中,等到其它的线程空闲后进行处理。

线程池作用:

1.降低资源消耗:通过重用已经创建的线程来降低线程创建和销毁的消耗

2.提高线程的可管理性:线程池可以统一管理、分配、调优和监控

3.降低程序的耦合程度: 提高程序的运行效率

4.多线程程序的运行效率, 是一个正态分布的结果, 线程数量从1开始增加, 随着线程数量的增加, 程序的运行效率逐渐变高, 直到线程数量达到一个临界值, 当在增加线程数量时, 程序的运行效率会减小(主要是由于频繁线程切换影响线程运行效率),所以并不是创建的线程越多性能越高

下面利用原生线程库来实现线程池

大家可以拷贝到VS Code下来看

代码中的一个解释

main.cc

#include<iostream>
#include<unistd.h>
#include<time.h>
#include"threadpool.hpp"

using namespace std;

int main()
{
    srand(time(nullptr) ^ getpid());

    ThreadPool<Task>* tp=new ThreadPool<Task>;
    tp->Start();
    while(true)
    {
        //1. 构建任务
        int x = rand() % 10 + 1;
        usleep(10);
        int y = rand() % 5;
        char op = opers[rand()%opers.size()];

        Task t(x, y, op);
        tp->Push(t);
        //2. 交给线程池处理
        std::cout << "main thread make task: " << t.GetTask() << std::endl;

        sleep(1);
    }
    return 0;
}

threadpool.hpp

#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include "task.hpp"

using namespace std;

struct ThreadInfo
{
    pthread_t tid;
    string name;
};

template <class T>
class ThreadPool
{
public:
    void Lock()
    {
        pthread_mutex_lock(&mutex_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }
    void Threadsleep()
    {
        pthread_cond_wait(&cond_, &mutex_);
    }
    void Wakeup()
    {
        pthread_cond_signal(&cond_);
    }
    bool IsQueueEmpty()
    {
        return tasks_.empty();
    }

    string GetThreadName(pthread_t tid)
    {
        for (const auto &ti : threads_)
        {
            if (ti.tid == tid)
                return ti.name;
        }
        return "None";
    }

public:
    ThreadPool(int num = 5) : threads_(num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }
    static void *HandlerTask(void *args) // 必须定义为静态函数,这样才不会传this指针过来,才不会导致函数不匹配问题
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        string name=tp->GetThreadName(pthread_self());
        while(true)
        {
            tp->Lock();
            while(tp->IsQueueEmpty())
            {
                tp->Threadsleep();
            }
            //消费任务
            T t=tp->Pop();
            tp->Unlock();
            //处理任务
            t();
            cout <<name << " run, "<< "result: " << t.GetResult() <<endl;

        }
        return nullptr;
    }
    
    void Start()
    {
        int size = threads_.size();
        for (int i = 0; i < size; i++)
        {
            threads_[i].name= "thread-" + to_string(i + 1);
            pthread_create(&(threads_[i].tid), nullptr, HandlerTask, this); // 传入this指针,使静态函数可以访问类内成员和函数
        }
    }
    T Pop()
    {
        T out=tasks_.front();
        tasks_.pop();
        return out;
    }
    void Push(const T& in)
    {
        //需要加锁
        Lock();
        tasks_.push(in);
        Wakeup();
        Unlock();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

private:
    vector<ThreadInfo> threads_; // 用数组管理创建出来的线程
    queue<T> tasks_;             // 用队列来管理任务

    pthread_mutex_t mutex_;
    pthread_cond_t cond_;
};

Task.hpp

#pragma once
#include <iostream>
#include <string>

using namespace std;
string opers="+-*/%";

enum
{
    Divzero = 1,
    Modzero,
    Unknown
};

class Task
{
public:
    Task()
    {}
    Task(int data1, int data2, char op) : _data1(data1), _data2(data2), _op(op), _result(0), _exitcode(0)
    {}
    void run()
    {
        switch (_op)
        {
        case '+':
        {
            _result = _data1+_data2;
            break;
        }
        case '-':
        {
            _result = _data1-_data2;
            break;
        }
        case '*':
        {
            _result = _data1*_data2;
            break;
        }
        case '/':
        {
            if (_data2 == 0) _exitcode = Divzero;
            else _result = _data1/_data2;
            break;
        }
        case '%':
        {
            if (_data2 == 0) _exitcode = Modzero;
            else _result = _data1%_data2;
            break;
        }
        default:
        {
            _exitcode=Unknown;
            break;
        }
        }
    }
    void operator()()
    {
        run();
    }
    string GetResult()
    {
        string r=to_string(_data1);
        r+=_op;
        r+=to_string(_data2);
        r+='=';
        r+=to_string(_result);
        r+='[';
        r+=to_string(_exitcode);
        r+=']';
        return r;
    }
    string GetTask()
    {
        string r=to_string(_data1);
        r+=_op;
        r+=to_string(_data2);
        r+="=?";
        return r;
    }

private:
    int _data1;
    int _data2;
    char _op;
    int _result;
    int _exitcode;
};

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

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

相关文章

如何使用ChatGPT,提示词篇之【编程代码】ChatGPT镜像网站

一、 ChatGPT可以做什么&#xff1f; ChatGPT能做的事情非常多&#xff01;它不仅仅是一个对话AI。以下是一些主要功能&#xff1a; 1. 回答问题&#xff1a;无论是学术问题、技术问题&#xff0c;还是生活琐事&#xff0c;ChatGPT都能提供帮助。 2. 写作助手&#xff1a;可以…

LeetCode - #124 二叉树中的最大路径和(Top 100)

文章目录 前言1. 描述2. 示例3. 答案关于我们前言 本题为 LeetCode 前 100 高频题 我们社区陆续会将顾毅(Netflix 增长黑客,《iOS 面试之道》作者,ACE 职业健身教练。)的 Swift 算法题题解整理为文字版以方便大家学习与阅读。 LeetCode 算法到目前我们已经更新到 123 期…

大语言模型知识点分享

1 目前主流的开源模型体系有哪些&#xff1f; Prefix Decoder 系列模型 核心点&#xff1a; 输入采用双向注意力机制&#xff0c;输出为单向注意力。双向注意力意味着输入的每个部分都可以关注到输入的所有其他部分&#xff0c;这在理解上下文时具有很强的优势。 代表模型&a…

智能监控,守护绿色能源:EasyCVR在电站视频监控中心的一站式解决方案

随着科技的飞速发展&#xff0c;视频监控技术在社会安全、企业管理及智慧城市建设等领域中扮演着越来越重要的角色。特别是在电力行业中&#xff0c;电站作为能源供应的关键设施&#xff0c;其安全性和稳定性至关重要。传统的人工监控方式已难以满足现代电站复杂多变的运行需求…

2024网安周 | 百度安全深度参与,探索人工智能与数字安全的融合发展之路

9月9日-15日&#xff0c;2024年国家网络安全宣传周在全国范围内统一举行&#xff0c;本届网安周继续以“网络安全为人民&#xff0c;网络安全靠人民”为主题&#xff0c;由中央宣传部、中央网信办、教育部、工业和信息化部、公安部、中国人民银行、国家广播电视总局、全国总工会…

计算机毕业设计 基于Python国潮男装微博评论数据分析系统的设计与实现 Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

BACnet-NPDU(4)

前面抓取了BACnet 的UDP和RS485数据进行分析&#xff0c;现在做一下总结。 BACnet不管是走UDP还是RS485&#xff0c;里面的NPDU和APDU数据结构是一样的&#xff0c;只是BACnet的头不一样&#xff0c;这里做一下总结。 1、UDP的BACnet 头 BACnet/IP 使用 UDP 协议进行数据传输&a…

【综合性渗透利器】- TscanPlus

如果你在寻找一款轻量级、实用且开源的漏洞扫描工具&#xff0c;那么 TscanPlus 绝对值得一试。这款工具由 TideSec 团队打造&#xff0c;以其简洁、高效、易用的特点&#xff0c;广受好评&#xff0c;目前在github上拥有1.5k star。 为什么推荐 TscanPlus&#xff1f; 无论你…

探索Kombo:AI与API的完美结合

文章目录 探索Kombo&#xff1a;AI与API的完美结合背景介绍库的定义安装指南简单函数使用场景应用常见问题及解决方案总结 探索Kombo&#xff1a;AI与API的完美结合 背景介绍 在当今快速发展的人工智能领域&#xff0c;Kombo库以其独特的优势脱颖而出。Kombo是一个专注于AI的…

Python项目Flask框架整合Redis

一、在配置文件中创建Redis连接信息 二、 实现Redis配置类 import redis from config.config import REDIS_HOST, REDIS_PORT, REDIS_PASSWD, REDIS_DB, EXPIRE_TIMEclass RedisDb():def __init__(self, REDIS_HOST, REDIS_PORT, REDIS_DB, EXPIRE_TIME, REDIS_PASSWD):# 建立…

《治愈老奶奶账号,AI涨粉玩法,简单好上手》第178期副业项目拆解

正文 一、项目介绍 今天给大家带来的是最新的一个暴力涨粉玩法&#xff0c;这个副业赛道玩法 15 天涨了 30 万粉。 大家可以看一下这个账号&#xff0c;发了有 58 多个作品&#xff0c;现在是 33 万粉&#xff0c; 这个属于是图文账号&#xff0c;做的是那种温暖治愈系类型的…

数据库管理-第245期 主流国产数据库RAC架构概览(20240929)

数据库管理245期 2024-09-29 数据库管理-第245期 主流国产数据库RAC架构概览&#xff08;20240929&#xff09;1 DMDSC2 KingBaseES RAC3 PolarDB4 Cantian5 HaloDB DLB/Data Sharding总结 数据库管理-第245期 主流国产数据库RAC架构概览&#xff08;20240929&#xff09; 作者…

uni-app - - - - - 小程序获取宿主语言

const systemInfo uni.getSystemInfoSync(); console.log(systemInfo);uni.showModal({title: 宿主语言,content: systemInfo.hostLanguage })官网地址&#xff1a;【uni-app getSystemInfoSync】

OpenCV C++霍夫圆查找

OpenCV 中的霍夫圆检测基于 霍夫变换 (Hough Transform)&#xff0c;它是一种从边缘图像中识别几何形状的算法。霍夫圆检测是专门用于检测图像中的圆形形状的。它通过将图像中的每个像素映射到可能的圆参数空间&#xff0c;来确定哪些像素符合圆形状。 1. 霍夫变换的原理 霍夫…

CRUD 开发工具 NocoBase 与 Refine 对比

引言 今天我们来聚焦两款非常优秀的开源 CRUD 开发工具&#xff1a;NocoBase 和 Refine&#xff0c;它们分别是无代码/低代码开发平台和低代码前端开发框架的典型代表。 特别值得一提的是&#xff0c;NocoBase 截止目前已经在GitHub 上获得了 12k 的 Star。Refine 作为 Retool…

AntFlow-Vue3 :一个仿钉钉流程审批,且满足99.8%以上审批流程需求的企业级工作流平台,开源且免费!

在现代企业管理中&#xff0c;流程审批的高效性直接影响到工作的流畅度与生产力。最近&#xff0c;我发现了一个非常有趣的项目—— AntFlow-Vue3 。这个项目不仅提供了一个灵活且可定制的工作流平台&#xff0c;还能让用户以可视化的方式创建和管理审批流程。 如果你是一名前…

828华为云征文|部署个人知识管理系统 SiyuanNote

828华为云征文&#xff5c;部署个人知识管理系统 SiyuanNote 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 SiyuanNote3.1 SiyuanNote 介绍3.2 SiyuanNote 部署3.3 Siyua…

【JavaScript】JQuery基础知识及应用

一、JQuery的导入方法 https://editor.csdn.net/md/?articleId132214798 二、JQuery介绍 JQuery(JQ)&#xff1a;JS的一个类库&#xff08;方法库&#xff1a;包含了大量的、有助于项目开发的属性和方法&#xff09; 第一代版本1.xx.xx: 1.11.3 兼容所有浏览器的&#xff0…

C语言 | Leetcode C语言题解之第443题压缩字符串

题目&#xff1a; 题解&#xff1a; void swap(char *a, char *b) {char t *a;*a *b, *b t; }void reverse(char *a, char *b) {while (a < b) {swap(a, --b);} }int compress(char *chars, int charsSize) {int write 0, left 0;for (int read 0; read < charsSi…

如何在NetCore8.0 Swagger 里配置多版本

话不多说 &#xff0c;先看效果 要做成以上效果也不难。请跟好脚步&#xff0c;下面带你们一步一步来做 首先要新建一个类 ApiVersionInfo public class ApiVersionInfo{/// <summary>/// 获取或者设置 V1 版本。/// </summary>public static string 软件版本 &qu…