C++面向对象实现封装线程池
body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}
面向对象:
| Noncopyable.h | Thread.h |
|
#ifndef __NONCOPYABLE_H__
#define __NONCOPYABLE_H__
#include<iostream>
using namespace std;
namespace meihao
{
class Noncopyable
{
public:
Noncopyable(){};
~Noncopyable(){};
private:
Noncopyable(const Noncopyable&);
Noncopyable& operator=(const Noncopyable&);
};
};
#endif
|
#ifndef __THREAD_H__
#define __THREAD_H__
#include<iostream>
#include"Noncopyable.h"
#include<pthread.h>
using namespace std;
namespace meihao
{
class Thread:private Noncopyable
{
public:
Thread();
void start();
void join();
virtual void run() = 0;
virtual ~Thread();
static void* threadFunc(void*);
private:
pthread_t _pthId;
bool _isRunning;
};
};
#endif
|
| MutexLock.h | Condition.h |
|
#ifndef __MUTEXLOCK_H__
#define __MUTEXLOCK_H__
#include<iostream>
#include"Noncopyable.h"
#include<pthread.h>
using namespace std;
namespace meihao
{
class MutexLock:public Noncopyable
{
public:
MutexLock();
~MutexLock();
void lock();
void unlock();
pthread_mutex_t* getMutexPtr();
private:
pthread_mutex_t _mutex;
};
};
#endif
|
#ifndef __CONDITION_H__
#define __CONDITION_H__
#include<iostream>
#include"MutexLock.h"
#include"Noncopyable.h"
using namespace std;
namespace meihao
{
class Condition:private Noncopyable
{
public:
Condition(MutexLock&);
~Condition();
void wait();
void notify();
void notifyall();
private:
pthread_cond_t _cond;
MutexLock& _mutex;
};
};
#endif
|
| Buffer.h | Task.h |
|
#ifndef __BUFFER_H__
#define __BUFFER_H__
#include<iostream>
#include"MutexLock.h"
#include"Condition.h"
#include"Task.h"
#include<queue>
using namespace std;
namespace meihao
{
typedef Task* DataType;
class Buffer:private Noncopyable
{
public:
Buffer(int);
void push(DataType);
DataType pop();
void wakeupEmpty(); // 唤醒所有等待队列不为空的线程
bool full();
bool empty();
private:
MutexLock _mutex;
Condition _notFull;
Condition _notEmpty;
int _queSize;
queue<DataType> _que;
bool _flag;
};
};
#endif
|
#ifndef __TASK_H__
#define __TASK_H__
#include<iostream>
using namespace std;
namespace meihao
{
class Task
{
public:
virtual void process() = 0; // 线程池里面的线程具体要做的任务
};
};
#endif
|
| Threadpool.h | ThreadpoolThread.h |
|
#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__
#include<iostream>
#include"Noncopyable.h"
#include"Task.h"
#include"Buffer.h"
#include<vector>
#include"Thread.h"
using namespace std;
namespace meihao
{
class Threadpool:private Noncopyable
{
public:
Threadpool(int,int);
void start();
void stop();
void addTask(Task*);
Task* getTask();
void threadFunc();
private:
int _threadNum;
vector<Thread*> _threadsVec; // 存放线程池里面的所有线程
int _bufSize;
Buffer _buf; // 缓冲区用来存放任务,到时候线程池从里面取走一个任务执行
bool _isExit;
};
};
#endif
|
#ifndef __THREADPOOLTHREAD_H__
#define __THREADPOOLTHREAD_H__
#include<iostream>
#include"Thread.h"
#include"Threadpool.h"
using namespace std;
namespace meihao
{
class Threadpoolthread:public Thread
{
public:
Threadpoolthread(Threadpool& threadpool):_threadpool(threadpool){}
void run()
{
_threadpool.threadFunc(); // 继承的线程池线程内部实现的线程执行体方法
// 调用线程池的threadFunc方法,线程池的所有线程都去执行这个方法
}
private:
Threadpool& _threadpool;
};
};
#endif
|
| Thread.cpp | MutexLock.cpp |
|
#include"Thread.h"
#include<iostream>
using namespace std;
namespace meihao
{
Thread::Thread():_pthId(0),_isRunning(false)
{
}
void Thread::start()
{
pthread_create(&_pthId,NULL,&Thread::threadFunc,this);
_isRunning = true;
}
void Thread::join()
{
if(_isRunning)
pthread_join(_pthId,NULL);
}
Thread::~Thread()
{
if(_isRunning)
pthread_detach(_pthId);
}
void* Thread::threadFunc(void* arg)
{
Thread* pthread = static_cast<Thread*> (arg);
if(NULL!=pthread)
pthread->run();
}
};
|
#include<iostream>
#include"MutexLock.h"
using namespace std;
namespace meihao
{
MutexLock::MutexLock()
{
pthread_mutex_init(&_mutex,NULL);
}
MutexLock::~MutexLock()
{
pthread_mutex_destroy(&_mutex);
}
void MutexLock::lock()
{
pthread_mutex_lock(&_mutex);
}
void MutexLock::unlock()
{
pthread_mutex_unlock(&_mutex);
}
pthread_mutex_t* MutexLock::getMutexPtr()
{
return &_mutex;
}
};
|
| Condition.cpp | Buffer.cpp |
|
#include"Condition.h"
#include<iostream>
using namespace std;
namespace meihao
{
Condition::Condition(MutexLock& mutex):_mutex(mutex)
{
pthread_cond_init(&_cond,NULL);
}
Condition::~Condition()
{
pthread_cond_destroy(&_cond);
}
void Condition::wait()
{
pthread_cond_wait(&_cond,_mutex.getMutexPtr());
}
void Condition::notify()
{
pthread_cond_signal(&_cond);
}
void Condition::notifyall()
{
pthread_cond_broadcast(&_cond);
}
};
|
#include<iostream>
#include"Buffer.h"
using namespace std;
namespace meihao
{
Buffer::Buffer(int size):_queSize(size)
,_mutex()
,_notFull(_mutex)
,_notEmpty(_mutex)
,_flag(true) // 开始,标志位true,表示buffer正常运行
// 后面线程池要结束的时候会修改为false
{
}
bool Buffer::full()
{
return _queSize == _que.size();
}
bool Buffer::empty()
{
return _que.size() == 0;
}
void Buffer::push(DataType elem)
{
_mutex.lock();
while(full())
{
_notFull.wait(); // 队列满,等待条件变量notFull满足
// 放到while里面是为了防止异常唤醒,唤醒的时候再次确认是否真的条件满足
}
_que.push(elem);
_notEmpty.notify();
_mutex.unlock();
}
DataType Buffer::pop()
{
_mutex.lock();
while(_flag&&empty()) // flag如果为false表示线程池等待回收线程stop线程池
{
_notEmpty.wait();
}
if(_flag)
{
DataType tmp = _que.front();
_que.pop();
_notFull.notify();
_mutex.unlock();
return tmp;
}
else
{
_mutex.unlock();
return NULL;
}
}
void Buffer::wakeupEmpty()
{
_flag = false;
_notEmpty.notifyall(); // 线程池在要关闭的时候会等待所有线程执行完挂在等待条件变量notEmpty上
//这个时候直接唤醒所有等待的线程
}
};
|
| test.cpp | Threadpool.cpp |
|
#include<iostream>
#include"Threadpool.h"
#include<unistd.h>
using namespace std;
class MyTask:public meihao::Task
{
public:
void process()
{
::srand(time(NULL));
int num = ::rand()%100;
cout<<"produce a num:"<<num<<endl;
}
};
int main()
{
meihao::Threadpool threadpool(4,10); // 定义一个线程池,里面有4个线程,去处理10个任务
threadpool.start();
meihao::Task* ptask = new MyTask(); // 定义一个具体的任务
int cnt = 10;
while(cnt--)
{
threadpool.addTask(ptask); // 线程池中添加任务
sleep(1);
}
threadpool.stop();
return 0;
}
|
#include"Threadpool.h"
#include<iostream>
#include"Threadpoolthread.h"
#include<unistd.h>
using namespace std;
namespace meihao
{
Threadpool::Threadpool(int threadNum,int bufSize):_threadNum(threadNum)
,_bufSize(bufSize) ,_buf(_bufSize) ,_isExit(false)
{
_threadsVec.reserve(_threadNum);
}
void Threadpool::start()
{
for(int i=0;i<_threadNum;++i)
{
Thread* pthread = new Threadpoolthread(*this); // 创建指定个数个线程
_threadsVec.push_back(pthread);
}
for(auto& elem:_threadsVec)
{
elem->start(); // 创造的线程开始启动
}
}
void Threadpool::stop()
{
if(!_isExit)
{
while(!_buf.empty()) // 如果缓冲池不空,也就是还有线程在执行
{
sleep(1); // 等待所有线程执行完
}
// 线程全部执行完将会都挂在_buf里面的_notEmpty的条件变量上
_buf.wakeupEmpty(); // 唤醒所有等待_notEmpty的线程
// 这个函数设置flag = false; 所有等待在Buffer里面的pop函数
// 里的线程将全部返回NULL
_isExit = true;
for(auto& elem:_threadsVec)
{
elem->join(); // 回收所有线程资源
delete elem;
}
}
}
void Threadpool::addTask(Task* task)
{
_buf.push(task);
}
Task* Threadpool::getTask()
{
return _buf.pop();
}
void Threadpool::threadFunc()
{
while(!_isExit)
{
Task* task = getTask();
if(task)
{
task->process();
}
}
}
};
|
C++面向对象实现封装线程池的更多相关文章
- 使用C++11封装线程池ThreadPool
读本文之前,请务必阅读: 使用C++11的function/bind组件封装Thread以及回调函数的使用 Linux组件封装(五)一个生产者消费者问题示例 线程池本质上是一个生产者消费者模型,所 ...
- c++简单线程池实现
线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他 ...
- java线程池及创建多少线程合适
java线程池 1.以下是ThreadPoolExecutor参数完备构造方法: public ThreadPoolExecutor(int corePoolSize,int maximumPoolS ...
- C++线程池的实现
线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他 ...
- Java线程池实现原理及其在美团业务中的实践
本文转载自Java线程池实现原理及其在美团业务中的实践 导语 随着计算机行业的飞速发展,摩尔定律逐渐失效,多核CPU成为主流.使用多线程并行计算逐渐成为开发人员提升服务器性能的基本武器.J.U.C提供 ...
- Java线程池实现原理及其在美团业务中的实践(转)
转自美团技术团队:https://tech.meituan.com/2020/04/02/java-pooling-pratice-in-meituan.html 随着计算机行业的飞速发展,摩尔定律逐 ...
- 面向对象的线程池Threadpool的封装
线程池是一种多线程处理形式,预先创建好一定数量的线程,将其保存于一个容器中(如vector), 处理过程中将任务添加到队列,然后从容器中取出线程后自动启动这些任务,具体实现如下. 以下是UML图,展示 ...
- c++封装编写线程池
在csapp学习或者其他linux底层编程的过程中,一般都会举一些多线程或多进程的例子,配合底层同步原语.系统调用api来解释怎么创建多线程/多进程. 但是这些例子和实际项目中所用到的多线程/多进程编 ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
随机推荐
- Servlet JDBC Example
Develop a web application that should have following features. User can register and then login to t ...
- Python 编程快速上手 第五章总结
第五章 字典和结构化数据 创建数组 格式:myCat = {'size':'fat','color':'gray',disposition':'loud'} 对字典的操作 通过[ ] 访问字典的值 [ ...
- samtools faidx输出的fai文件格式解析 | fasta转bed | fasta to bed
fai示例: Sc0000003 2774837 10024730 60 61 Sc0000004 2768176 12845826 60 61 Sc0000005 2756750 15660150 ...
- 深入解析 composer 的自动加载原理 (转)
深入解析 composer 的自动加载原理 转自:https://segmentfault.com/a/1190000014948542 前言 PHP 自5.3的版本之后,已经重焕新生,命名空间.性状 ...
- Linux 权限管理命令
第四章(二)权限管理命令 Linux常用命令(二)权限管理命令
- 6月5 Smarty变量调节器
变量调节器:<{$a|变量调节器}> 主要修改此页面的信息来了解变量调节器:test0605/main.php和模板文件:main0605.html 1.利用给定的变量调节器 capita ...
- 【IDEA】【8】上传已有项目到Git
问题:开发初期没有建立GIT仓库,开发一段时间后,需要将已有代码上传到Git 解决方案: 1,首先使用Git命令行 git clone XXXXX.git 将项目下载 2,拷贝下载下来的项目根目录下的 ...
- jquery获取和设置值
1.html html() : 取得第一个匹配元素的html内容. html(value): 设置每一个匹配元素的html内容 2text text() : 取得所有匹配元素的内容,结果是由所有 ...
- ABAP游标
DATA: BEGIN OF count_line, carrid TYPE spfli-carrid, count TYPE i, END OF count_line, spfli_tab TYPE ...
- TSFDEVTY
TSFDEVTY 用BAPI_OUTB_DELIVERY_CONFIRM_DEC做的发货过账,会VL09无法冲销需要UPDATE LIKP-VLSTK为空UPDATE likp SET vlstk = ...