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的基本用法,到简单的封装,再到 ...
随机推荐
- Windows 下 Redis 服务无法启动,错误 1067 进程意外终止解决方案
1.检查端口是否被占用 2.修改 Windows 服务里的 Redis 服务为本地系统服务(修改方式见下文) 方法: 1.看系统日志 桌面计算机/此电脑(Win10名称)右键打开管理,或 Win+R ...
- spring cloud: Hystrix(一):简单使用
在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能 ...
- 一款好用的取色工具TakeColor
简介:TakeColor,一款还算好用的取色软件,一个很小很简洁的exe文件,无需安装 使用:打开exe文件后,使用“Alt + C” 组合键即可在鼠标悬停的位置上获取到颜色值,可以获取HTML.RG ...
- LeetCode--003--无重复字符的最长子串(java)
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...
- RMQ 解决区间查询问题
线段树写法不管,比较灵活.这里主要讨论DP实现. 其实单纯说RMQ解决的是区间最值查询是不准确的,只要满足一个区间的信息可以从它的覆盖区间获得(即[L,R]<=[L,r],[l,R] (l< ...
- java控制流
目录 1.引用数据类型 2.流程控制语句 2.1 条件控制语句if 2.2 if语句与三元运算符的互换 2.3 循环语句 2.4 循环嵌套 2.5 跳转语句 2.6 选择结构switch 3.猜数字案 ...
- 『MXNet』第七弹_多GPU并行程序设计
资料原文 一.概述思路 假设一台机器上有个GPU.给定需要训练的模型,每个GPU将分别独立维护一份完整的模型参数. 在模型训练的任意一次迭代中,给定一个小批量,我们将该批量中的样本划分成份并分给每个G ...
- spring boot(十六)使用Jenkins部署spring boot
jenkins是devops神器,本篇文章介绍如何安装和使用jenkins部署Spring Boot项目 jenkins搭建 部署分为三个步骤: 第一步,jenkins安装 第二步,插件安装和配置 第 ...
- 突破本地离线存储5M限制的JS库localforage简介
http://www.zhangxinxu.com/wordpress/2018/06/js-localforage-localstorage-indexdb/
- leetcode-algorithms-6 ZigZag Conversion
leetcode-algorithms-6 ZigZag Conversion The string "PAYPALISHIRING" is written in a zigzag ...