C++11 线程池的使用

2023-05-16

        本文主要介绍C++中线程池的实现以及C++11中新特性(仿函数、线程、互斥量、原子、条件变量等)的使用,最终会实现一个简易的线程池,可支持传参不传参等任务。

目录

一、线程池的用途

1、线程池的作用

二、线程池的实现思路

1、线程池类头文件

2、线程池类源文件

3、使用线程池

三、不足和缺陷

一、线程池的用途

1、线程池的作用

        频繁的创建和销毁线程会产生大量的程序资源消耗。使用线程池来管理线程的创建和销毁, 有助于提高线程创建和销毁过程的效率。线程池的本质就是提前创建一堆线程,在程序需要使用线程来执行任务的时候,将任务放置到线程池中交给未执行任务的线程执行,从而提高了程序的运行效率,提高了线程的利用率。

二、线程池的实现思路

1、线程池类头文件

#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <iostream>
#include <thread>
#include <functional>
#include <queue>
#include <vector>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <chrono>

class CThreadPool
{
    using Task = std::function<void()>;
private:
    CThreadPool();
    ~CThreadPool();
    CThreadPool(const CThreadPool&) = delete;
    CThreadPool& operator=(const CThreadPool&) = delete;
public:
    static CThreadPool& GetInstance();

    void SetMaxThreadNum(const int iCount);

    void OnStart();

    void OnStop();

    void AppendTask(const Task& _task);

private:
    void DoWork();

private:
    std::atomic_bool m_bIsRunning{false};
    unsigned short m_usThreadNum{2};
    std::vector<std::thread> m_vctThreads;
    std::queue<Task> m_queTasks;
    std::condition_variable m_cv;
    std::mutex m_mtx;
};



#endif /* THREADPOOL_H */

2、线程池类源文件

#include "../include/threadpool.h"
CThreadPool::CThreadPool()
{

}
CThreadPool::~CThreadPool()
{
    OnStop();
}

CThreadPool& CThreadPool::GetInstance()
{
    static CThreadPool instance;
    return instance;
}

void CThreadPool::SetMaxThreadNum(const int _iCount)
{
    m_usThreadNum = _iCount;
}

void CThreadPool::OnStart()
{
    m_bIsRunning = true;
    
    for (int iIndex = 0; iIndex < m_usThreadNum; ++iIndex)
    {
        m_vctThreads.emplace_back(std::thread(&CThreadPool::DoWork, this));
    }
}

void CThreadPool::OnStop()
{
    {
        std::unique_lock<std::mutex> ulock(m_mtx);
        m_bIsRunning = false;
        m_cv.notify_all();
    }
    for (auto& td : m_vctThreads)
    {
        if (td.joinable())
        {
            td.join();
        }
    }
}

void CThreadPool::AppendTask(const Task& _task)
{
    std::unique_lock<std::mutex> ulock(m_mtx);
    m_queTasks.push(_task);
    m_cv.notify_one();
}

void CThreadPool::DoWork()
{
    while(m_bIsRunning)
    {
        Task task;
        {
            std::unique_lock<std::mutex> ulock(m_mtx);
            if (!m_queTasks.empty())
            {
                task = m_queTasks.front();
                m_queTasks.pop();
            }
            else if (m_queTasks.empty() && m_bIsRunning)
            {
                m_cv.wait(ulock);
            }
        }

        if (task)
        {
            std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
            task();
            std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

            std::cout << (std::chrono::time_point_cast<std::chrono::microseconds>(end) - 
                  std::chrono::time_point_cast<std::chrono::microseconds>(start)).count() /1000000.00<< std::endl; 
        }
        
    }
}

3、使用线程池

#include "include/threadpool.h"

std::mutex mtx;
void Test(int iValue)
{
    std::unique_lock<std::mutex> ulock(mtx);
    std::cout<<std::this_thread::get_id()<<" thread execute...."<<iValue<<std::endl;
}
int main(int argc, char* argv[])
{
    CThreadPool::GetInstance().SetMaxThreadNum(4);
    CThreadPool::GetInstance().OnStart();
    for (int i=0; i<100; i++)
    {
        CThreadPool::GetInstance().AppendTask(std::bind(Test, i));
    }
    std::this_thread::sleep_for(std::chrono::seconds(10));
    CThreadPool::GetInstance().OnStop();
    return 0;
}

三、不足和缺陷

        在上文中线程池没有实现任务的优先级,有时还需要使用任务的执行结果,这些都没有处理,后续在完善,欢迎大家指导和提出宝贵意见。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11 线程池的使用 的相关文章

  • UE4添加音乐、音效

    目录 一 目的 xff1a 1 想 xff1a UE4添加音乐 音效 二 参考 1 三 操作 xff1a 完成 1 前述 xff1a 1 导入音乐 1 创建Cue 1 Cue进行设置 1 创建音乐 1 播放和暂停音乐 一 目的 xff1a
  • 《嵌入式C语言自我修养》书评

    首先 xff0c 介绍本书的内容 笔者从嵌入式工程师的视角出发 xff0c 先为我们初学者补上硬件相关基础 xff0c 如计算机工作原理和系统结构 xff08 理解程序编译 链接 安装和运行机制 xff09 CPU的工作原理 xff08 理
  • SLAM14讲之第五讲--像素坐标系、畸变、双目相机深度求解

    像素坐标系 由相似三角形的定义可得 xff1a 这是相对于成像平面的坐标变化 xff0c 我们实际上所得到的图片还要经历一层成像平面到像素平面的变换 xff0c 实际上就是相差了一个缩放和原点的平移 如此我们定义 xff1a u为横轴向右与
  • python webkit 异步抓取页面数据

    usr bin python from ghost import Ghost class FetcherCartoon def getCartoonUrl self url if url is None return false todo
  • 树莓派 Ubuntu mate 16.04使用VNC开启远程桌面

    1 安装 vncserver sudo apt span class token operator span get span class token operator span y install vnc4server 2 启动 vncs
  • 数学建模(四)-----最优化问题-----Simulate Anneal Arithmetic

    模拟退火算法的应用很广泛 xff0c 可以较高的效率求解最大截问题 Max Cut Problem 0 1背包问题 Zero One Knapsack Problem 图着色问题 Graph Colouring Problem 调度问题 S
  • 路径规划的优化

    因为这个求N个点的最短路径是将把所有可能的走法都可能尝试一遍 这样的话 如果计算十几个点之间的最短路径是没有问题的 但是问题就在如果超过二十个点位 那么最坏的情况就是需要计算20的阶乘个 这个计算是相当高的 可能会把线上的服务器打爆 或者计
  • SPL06电容式压力传感器数据读取与处理(基于STM32)

    该例程使用的开发板为正点原子的精英板F103 xff0c 相关资料请大家自行去正点原子论坛下载 首先来看一下SPL06的简介 xff0c SPL06的压强测量范围30kPa 110kPa xff0c 最大供电电压为3 6V xff0c 相对
  • 企业微信开发实战(六、自建应用-审批流程引擎之配置可信任域名、创建审批模版、发起审批)

    文章目录 4 自建应用审批状态变化通知回调4 1概述4 2代码实战 5 查询自建应用审批单当前状态5 1概述5 2代码实战 源码赞赏 4 自建应用审批状态变化通知回调 4 1概述 1 企业可以在管理后台 自建应用 设置API接收中 xff0
  • FreeRTOS内存管理之heap_4.c

    FreeRTOS内存管理之heap 4 c源码解析 每当创建任务 队列 互斥量 软件定时器 信号量或事件组时 xff0c RTOS内核会为它们分配RAM 标准函数库中的malloc 和free 函数有些时候能够用于完成这个任务 xff0c
  • git图形化管理工具

    一 独立客户端工具 1 GitHub for Desktop 全球开发人员交友俱乐部提供的强大工具 xff0c 功能完善 xff0c 使用方便 对于使用GitHub的开发人员来说是非常便捷的工具 界面干净 xff0c 用起来非常顺手 xff
  • ROS功能包

    ROS package介绍 package是什么呢 xff1f 指的是一种特定的文件结构和文件夹组合 通常将实现同一个具体功能的程序代码放到一个package中 xff0c 比如实现相机数据采集这一功能 文件结构 CMakeLists tx
  • 坐标转换tf

    tf介绍 坐标转换 TransForm 位置和姿态 坐标变换是空间实体的位置描述 xff0c 是从一种坐标系统变换到另一种坐标系统的过程 通过建立两个坐标系统之间一一对应关系来实现下图为机器人几个部件之间的坐标关系 tf概念 tf是一个用户
  • 经典Windows编程书单

    说好的这次写一个图形编程书单 但是看起来不是很好整理 xff0c 这类书散落的家里到处都是 先把经典Windows编程的书整理一下吧 xff0c 不过Windows的也到处都是很多都找不到了 xff0c 只能把找到的拍个照 xff0c 可能
  • vscode设置C++代码格式化(Clang-Format)

    vscode中只要安装了C C 43 43 扩展后 xff0c 在C C 43 43 源文件中右键就能看到格式化文档的选项 xff0c 这样就能通过该选项或者其快捷键 xff08 Shift 43 Alt 43 F xff09 来实现快速格
  • git pull覆盖了本地未push的代码解决方案

    一 问题背景 情况 xff1a 本地代码写完后 xff0c git push上去github xff0c 然后报错 xff0c 提示要先git pull pull之后 xff0c 失败了或者覆盖了本地未push的代码 二 解决方案 2 1
  • FreeRTOS任务调度原理

    1 FreeRTOS的列表和列表项 列表和列表项是FreeRTOS中一个非常重要的数据结构 xff0c 是FreeRTOS的基石 要想看懂FreeRTOS的源码并学习其中的原理 xff0c 我们必须先了解一下这个数据结构 这个数据结构也是和
  • Go语言学习教程(十四)

    一 反射介绍 在Go语言标准库中reflect包提供了运行时反射 程序运行过程中动态操作结构体 当变量存储结构体属性名称 想要对结构体这个属性赋值或查看时 就可以使用反射 反射还可以用作判断变量类型 整个reflect包中最重要的两个类型
  • 正点原子FPGA学习笔记4.4——UART串口通信,基于达芬奇开发板 A7

    目录 1 环回模块 协调发送接收模块 0 综上 xff0c 信号线如下 xff1a 1 捕捉发送模块传过来recv done信号的上升沿 得到recv done flag 2 recv done flag拉高 xff0c 接收了一帧数据 x
  • UBUNTU 下面的DOCKER使用图形界面

    ubuntu下docker容器中开启图形界面 xff1a 转载自 xff1a https blog csdn net ericcchen article details 79253416 方法一 xff1a 开启SSH服务 详细开启流程 x

随机推荐