C++ 线程池的简易实现
时间:2022-07-26
本文章向大家介绍C++ 线程池的简易实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
首先,先简单介绍,线程池的工作原理。
1.他自身拥有一定数量的线程数组 threads,处于等待状态,等待唤醒(通过条件变量)
2.拥有一个任务队列 m_tasks,存储用户的任务,有新任务以后,唤醒线程,取出任务,通过回调函数的方式调用任务,执行完以后继续等待。
使用情况:线程池,适用于会话简短的情况下,http访问可以使用线程池,如需要长时间保持通讯的,如会话,就不要用线程池了。
本例子,采用单例模式,线程安全。
公开接口两个:
static CMyThreadPool * getInstance(); bool start(Task fun);
用户的函数 fun 的参数,可通过,bind来传递,不过要注意,如果传的是指针,需要注意他的生存周期,如果传的是 new,处理完以后,要自己 delete.
void showTicket(mutex* m){
lock_guard<std::mutex> l(*m);
cout <<" show ticket: " << ticket++ << endl;
}
pool->start(bind(showTicket, m));
头文件:
//定义一个函数对象类型
typedef std::function<void()> Task;
class CMyThreadPool
{
private:
int max_thread; // max thread;
int max_task; // max task;
// thread array:
vector<thread> threads;
// task queue:
queue<Task> m_tasks;
// lock:
mutex m_lock;
// condition:
condition_variable has_task;
bool running_flag;
public:
~CMyThreadPool(void);
//获取线程池对象指针
static CMyThreadPool * getInstance();
//添加任务,成功返回true,失败返回false
bool start(Task fun);
private:
CMyThreadPool(void);
bool InitThread();
void DestroyPool();
//工作线程
void WorkFun();
static CMyThreadPool * m_pool;
static std::mutex *singal_mutex;
};
实现:
#include "MyThreadPool.h"
CMyThreadPool * CMyThreadPool::m_pool = NULL;
mutex* CMyThreadPool::singal_mutex = new mutex();
CMyThreadPool::CMyThreadPool(void):max_thread(default_max_thread),
max_task(default_max_task),running_flag(true)
{
}
CMyThreadPool::~CMyThreadPool(void)
{
DestroyPool();
}
CMyThreadPool * CMyThreadPool::getInstance()
{
if( NULL == m_pool){
//lock();
std::lock_guard<std::mutex> l(*singal_mutex);
if( NULL == m_pool){
m_pool = new CMyThreadPool();
}
//unlock();
}
return m_pool;
}
bool CMyThreadPool::start( Task fun )
{
//判断是否第一次,延缓线程初始化
{
if( threads.size() == 0){
unique_lock<mutex> l(m_lock);
if( threads.size() == 0){
//初始化线程
if(!InitThread()){
return false;
}
}
}
}
//判断工作队列是否已满,没满则加入工作队列
{
unique_lock<mutex> l(m_lock);
if( (unsigned int)max_task > m_tasks.size()){
m_tasks.push(fun);
}else{
return false;
}
}
//唤醒一个线程
has_task.notify_one();
return true;
}
//已经上着锁了
bool CMyThreadPool::InitThread()
{
for (int i = 0; i != max_thread; i++){
threads.push_back(thread(&CMyThreadPool::WorkFun, this));
}
return true;
}
void CMyThreadPool::WorkFun()
{
while(running_flag || !m_tasks.empty()){
Task t;
//获取task
{
unique_lock<mutex> l(m_lock);
while( m_tasks.empty())
has_task.wait(l);
t = m_tasks.front();
m_tasks.pop();
}
//执行task
t();
}
}
void CMyThreadPool::DestroyPool()
{
{
unique_lock<mutex> u_lock(m_lock);
running_flag = false;
}
has_task.notify_all();
for( auto &t : threads){
t.join();
}
threads.clear();
}
测试用例:
#include <iostream>
#include "MyThreadPool.h"
#include <memory>
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <Windows.h>
using namespace std;
int ticket = 0;
void showTicket(mutex* m){
lock_guard<std::mutex> l(*m);
#ifdef WIN32
//打印当前线程号
cout << "Thread id: " << GetCurrentThreadId();
#endif
cout <<" show ticket: " << ticket++ << endl;
}
int main(){
mutex *m = new mutex;
int sum = 0;
{
std::shared_ptr<CMyThreadPool> pool(CMyThreadPool::getInstance());
for(int i = 0; i < 100;i++){
if(!pool->start(bind(showTicket, m))){
sum++;
}
}
}
cout << "not use task : "<< sum << endl;
delete m;
_CrtDumpMemoryLeaks();
system("pause");
return 0;
}
- 走索引扫描的慢查询(r3笔记45天)
- AR(I)MA时间序列建模过程——步骤和python代码
- 用python作信用卡欺诈预测
- 联系生活来简化sql(r3笔记第43天)
- [笔记]使用Python一步一步地来进行数据分析
- 使用 R 语言从拉勾网看数据挖掘岗位现状
- 使用strace分析exp的奇怪问题(r3笔记第41天)
- Python文本挖掘:知乎网友如何评价《人民的名义》
- 怎样做中文文本的情感分析?
- 由一条日志警告所做的调优分析(r3笔记第40天)
- 生产环境sql语句调优实战第十篇(r3笔记第39天)
- memory_target设置不当导致数据库无法启动的问题(r3笔记第38天)
- python利用结巴分词做新闻地图
- 数据库静默安装总结(r3笔记第58天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ELK+FileBeat+Kafka分布式系统搭建图文教程
- Flink CEP 原理和案例详解
- 实战开发,使用 Spring Session 与 Spring security 完成网站登录改造!!
- 分布式计算框架Gearman原理详解
- 【从0开始の全记录】Flume+Kafka+Spark+Spring Boot 统计网页访问量项目
- 系统级性能分析工具perf的介绍与使用[转]
- 深入理解排序算法
- 用nginx缓存静态文件
- 优雅的玩PHP多进程
- 聊一聊mycat数据库集群系列之双主双重实现
- Fast-SCNN的解释以及使用Tensorflow 2.0的实现
- 基于Spring Boot快速实现发送邮件功能
- 史上最全的vim快捷键文档/手册/大全/帮助/指南
- RPC详解
- 轻松学Pytorch – 行人检测Mask-RCNN模型训练与使用