C++11 简单实现线程池的方法

 更新时间:2020年10月27日 09:57:49   作者:轻风々  
这篇文章主要介绍了C++11 简单实现线程池的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

什么是线程池

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

不使用线程池有哪些弊端

创建太多线程,将会浪费一定的资源,有些线程未被充分使用。
销毁太多线程,将导致之后浪费时间再次创建它们。
创建线程太慢,将会导致长时间的等待,性能变差。
销毁线程太慢,导致其它线程资源饥饿。

线程池的组成部分

1、线程池管理器(ThreadPoolManager):用于创建并管理线程池
2、工作线程(WorkThread): 线程池中线程
3、任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
4、任务队列:用于存放没有处理的任务。提供一种缓冲机制

下面直接看代码实现

ThreadPoolManage.hpp

#pragma once
#include <thread>
#include <vector>
#include <queue>
#include <condition_variable>
#include <mutex>
/*
* 抽象一个任务 根据自己的需求扩展
*/
class AbsTask 
{
public:
 AbsTask() = default;
 virtual ~AbsTask() = default;
public:
 virtual void run() = 0;
};
template<class _Ty>
class ThreadPoolManage
{
public:
 ThreadPoolManage(unsigned int nMaxThread)
 :mMaxThreadNum(nMaxThread)
 , mThreadStatus(false)
 {
 //启动的时候就要创建线程
 auto maxNum = std::thread::hardware_concurrency();
 //获取当前操作系统中CPU的核心数量 根据核心数量来设置 最大工作线程的并发数量
 mMaxThreadNum = mMaxThreadNum > maxNum ? maxNum : mMaxThreadNum;
 //创建工作线程池
 for (auto i = 0; i < mMaxThreadNum; i++)
 {
  mWorkers.emplace_back([this] {
  while (true)
  {
   std::unique_lock<std::mutex> lock(this->mQueue_mutex);
   this->mCondition.wait(lock, [this]() {return this->mThreadStatus || !this->mTasks.empty(); });
   if (this->mThreadStatus && this->mTasks.empty()) 
   { 
   return; 
   }
   //获取队列头部的任务
   auto task = std::move(this->mTasks.front());
   //任务出队
   this->mTasks.pop();
   //执行工作
   task.run();
  }
  });
 }
 }
 ~ThreadPoolManage()
 {

 {
  std::unique_lock<std::mutex> lock(this->mQueue_mutex);
  this->mThreadStatus = true;
 }
 //通知所有线程起来工作 然后退出
 this->mCondition.notify_all();
 //等待所有线程工作完毕
 for (std::thread& worker : this->mWorkers) 
 {
  if (worker.joinable()) {
  worker.join();
  }
 }
 }
 /*
 * 添加任务到任务队列
 */
 void addTask(_Ty& task)
 {
 std::unique_lock<std::mutex> lock(this->mQueue_mutex);
 if (mThreadStatus) {
  throw std::runtime_error("workers stop");
 }
 mTasks.emplace(std::move(task));
 mCondition.notify_one();
 }
private:
 /*
 * 工作线程池
 */
 std::vector<std::thread> mWorkers;
 /*
 * 任务队列
 */
 std::queue<_Ty> mTasks;
 /*
 工作线程的最大并发数量
 */
 unsigned int mMaxThreadNum;
 /*
 条件变量 控制线程池中线程的工作状态
 */
 std::condition_variable mCondition;
 /*
 * 工作线程锁
 */
 std::mutex mQueue_mutex;
 /*
 * 控制线程的开关 false 继续工作 true 退出线程
 */
 bool mThreadStatus;

};

调用代码

main.cpp

#include <iostream>
#include <chrono>
#include "ThreadPool.hpp"
class Task :public AbsTask
{
public:
 void run() override
 {
 std::this_thread::sleep_for(std::chrono::seconds(1));
 std::cout << "works ...... " << std::this_thread::get_id() << std::endl;
 }
};
int main()
{
 ThreadPoolManage<Task> ThreadPool(8);
 for (size_t i = 0; i < 256; i++)
 {
 Task task;
 ThreadPool.addTask(task);
 }
 std::cin.get();
 system("pause");
}

到此这篇关于C++11 简单实现线程池的方法的文章就介绍到这了,更多相关C++11 线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C/C++ 开发神器CLion使用入门超详细教程

    C/C++ 开发神器CLion使用入门超详细教程

    这篇文章主要介绍了C/C++ 开发神器CLion使用入门超详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • C++实现LeetCode(35.搜索插入位置)

    C++实现LeetCode(35.搜索插入位置)

    这篇文章主要介绍了C++实现LeetCode(35.搜索插入位置),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++中标准线程库的基本使用介绍

    C++中标准线程库的基本使用介绍

    大家好,本篇文章主要讲的是C++中标准线程库的基本使用介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • 提高C程序效率的10种有效方法

    提高C程序效率的10种有效方法

    本文向你介绍规范你的C代码的10种方法。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • 深入解读C++中的指针变量

    深入解读C++中的指针变量

    这篇文章主要介绍了深入解读C++中的指针变量,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++虚继承的实现原理由内存布局开始讲起

    C++虚继承的实现原理由内存布局开始讲起

    为了解决多继承时的命名冲突和冗余数据问题,C++提出了虚继承,使得在派生类中只保留一份间接基类的成员,下面我们从内存布局看看虚继承的实现原理
    2022-06-06
  • C语言实现2048小游戏

    C语言实现2048小游戏

    这篇文章主要为大家详细介绍了C语言实现2048小游戏,注释清晰,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • c++ 解决无法打印uint8_t 类型变量的问题

    c++ 解决无法打印uint8_t 类型变量的问题

    这篇文章主要介绍了c++ 解决无法打印uint8_t 类型变量的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 深入分析:C++模板究竟会使代码膨胀吗

    深入分析:C++模板究竟会使代码膨胀吗

    今天和同事说到C++模板会使代码膨胀, 可同事觉得不会。 同事的依据是: 如果模板会使代码膨胀, 那么ATL和WTL里为什么还要大量使用模板? 同样功能 ,ATL和WTL编译出的可执行文件可比MFC编译的要小的多
    2013-04-04
  • C语言实现基于控制台的电子时钟

    C语言实现基于控制台的电子时钟

    这篇文章主要为大家详细介绍了C语言实现基于控制台的电子时钟,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论