目录
一、LockGuard.hpp
二、Task.hpp
三、Thread.hpp
四、ThreadPool.hpp
#pragma once
#include
#include
class Mutex//锁的对象
{
public:
Mutex(pthread_mutex_t* lock_p=nullptr)
:_lock_p(lock_p)
{}
~Mutex()
{}
void lock()
{
if(_lock_p)
{
pthread_mutex_lock(_lock_p);
}
}
void unlock()
{
if(_lock_p)
{
pthread_mutex_unlock(_lock_p);
}
}
private:
pthread_mutex_t* _lock_p;//锁的指针
};
class LockGuard//加锁和解锁的类
{
public:
LockGuard(pthread_mutex_t* mutex)
:_mutex(mutex)
{
_mutex.lock();//在构造函数进行加锁
}
~LockGuard()
{
_mutex.unlock();//在析构函数进行解锁
}
private:
Mutex _mutex;
};
#pragma once
#include
#include
#include
class Task
{
//using func=std::function;
typedef std::function func_t;//函数对象
public:
Task()
{}
Task(int x,int y,char op,func_t func)
:_x(x)
,_y(y)
,_op(op)
,_callBack(func)
{}
std::string operator()()//消费者调用
{
int result=_callBack(_x,_y,_op);
char buffer[1024];
snprintf(buffer,sizeof(buffer),"%d %c %d=%d",_x,_op,_y,result);//结果字符串
return buffer;
}
std::string toTaskString()//生产者调用
{
char buffer[1024];
snprintf(buffer,sizeof(buffer),"%d %c %d=?",_x,_op,_y);
return buffer;
}
private:
int _x;
int _y;
char _op;//加减乘除取模
func_t _callBack;//回调函数
};
const std::string oper = "+-*/%";
int myMath(int x, int y, char op)
{
int result = 0;
switch (op)
{
case '+':
result = x + y;
break;
case '-':
result = x - y;
break;
case '*':
result = x * y;
break;
case '/':
{
if (y == 0)
{
std::cerr << "div zero error" << std::endl;
result = -1;
}
else
result = x / y;
}
break;
case '%':
{
if (y == 0)
{
std::cerr << "mod zero" << std::endl;
result = -1;
}
else
result = x % y;
}
break;
default:
std::cout<<"运算符输入有误"<
#pragma once
#include
#include
#include
#include
#include
namespace ThreadNs
{
typedef std::function func_t;//定义一个函数对象类型,它的返回值和参数都是void*
const int num = 1024;
class Thread
{
private:
//因为形参有个this指针,所以弄成static
static void* start_routine(void* args)//这里的args就是 start()的ctx
{
Thread* _this=static_cast(args);
return _this->callback();
}
void* callback()
{
return _func(_args);
}
public:
//构造函数
Thread()
{
char nameBuffer[num];
snprintf(nameBuffer,sizeof(nameBuffer),"thread-%d",threadNum++);
_name=nameBuffer;
}
void start(func_t func,void* args=nullptr)//线程启动
{
_func=func;
_args=args;
int n=pthread_create(&_tid,nullptr,start_routine,this);
assert(n==0);
(void)n;
}
void join()
{
int n=pthread_join(_tid,nullptr);
assert(n==0);
(void)n;
}
std::string threadName()
{
return _name;
}
~Thread()
{}
private:
std::string _name;//线程的名字
func_t _func;//线程的回调函数
void* _args;//喂给线程的参数
pthread_t _tid;//线程ID
static int threadNum;//线程编号,最好自己再加个锁
};
int Thread::threadNum=1;
//异常和if。意料之外
//assert。意料之中。99%概率为真。
}
#pragma once
#include
#include
#include
#include
#include
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace ThreadNs;
const int gnum =5;
template //声明
class ThreadPool;
template
struct ThreadData
{
ThreadData(ThreadPool* tp,const std::string& s)
:_threadPool(tp)
,_name(s)
{}
ThreadPool* _threadPool;
std::string _name;
};
template
class ThreadPool
{
private:
//因为普通成员函数第一个参数是this指针,和回调方法不匹配,故改成static类型
static void* handlerTask(void* args)//args是ThreadData对象指针
{
ThreadData* td=static_cast*>(args);
while(1)
{
T t;
{ //RAII,出了作用域LockGuard会销毁,将析构锁
LockGuard lockGuard(td->_threadPool->mutex());//加锁
while(td->_threadPool->IsQueueEmpty())//如果队列为空,则等待
{
td->_threadPool->ThreadWait();
}
//线程能走到这里,说明队列一定有任务给线程
t=td->_threadPool->Pop();//从队列中取出任务
}
std::cout<_name<<"已获取任务:"<&)=delete;//禁用拷贝构造
ThreadPool& operator=(const ThreadPool&)=delete;//禁用赋值运算符重载
public://解决静态handlerTask是静态函数的问题,这几个都是偷家函数
void LockQueue() {pthread_mutex_lock(&_mutex);}
void UnLockQueue() {pthread_mutex_unlock(&_mutex);}
bool IsQueueEmpty(){return _taskQueue.empty();}
void ThreadWait() {pthread_cond_wait(&_cond,&_mutex);}
T Pop()
{
T t=_taskQueue.front();
_taskQueue.pop();
return t;
}
pthread_mutex_t* mutex()
{
return &_mutex;
}
public:
void run()//线程启动
{
for(const auto& t:_threads)
{
ThreadData* td=new ThreadData(this,t->threadName());
t->start(handlerTask,(void*)td);
std::cout<threadName()<<"start..."<* getInstance()//这里的static的作用是让这个函数只有一份,获取单例对象。tp是临界资源,需要加锁
{
if(nullptr==tp)//因为锁只创建一次,防止线程进来被锁阻塞
{
//只进来一次就够了
_singletonLock.lock();
if(nullptr==tp)//说明对象还没有被创建
{
tp=new ThreadPool();
}
_singletonLock.unlock();
}
return tp;
}
private:
int _num;//线程个数
std::vector _threads;//使用vector存放线程
std::queue _taskQueue;//任务队列,往里面放任务,它是共享资源,需要加锁保护
pthread_mutex_t _mutex;//互斥锁
pthread_cond_t _cond;//条件变量
static ThreadPool* tp;//单例模式静态的对象指针
static std::mutex _singletonLock;//获取单例对象使用的锁
};
template
ThreadPool* ThreadPool::tp=nullptr;
template
std::mutex ThreadPool::_singletonLock;
1、调用getInstance时需要加锁,防止多个线程同时调用,实例化出多份对象。
2、双重if判断,避免不必要的锁竞争。