Windows C++ 线程池

来源:互联网 发布:阿里云机房测速 编辑:程序博客网 时间:2024/04/30 18:51

        Windows 平台C++ 没什么比较好的官方的线程池,boost里倒是有很方便的线程池,可是为了一个线程池,使用庞大的boost显然不太合适,为此,我在网上找了个demo,然后用C++模板做了些改造,基本上实现了类似boost的threadpool的功能。

首先需要解释的是,以何种方式将线程函数加入队列(我这里用的队列是CList),可以利用类模板和函数模板以及函数指针创建包含该函数的对象,执行时,只需要调用对象中的函数指针即可,这里说明下,因为函数模板在实例化之前是没有任何函数的,因此,自然就不存在指向函数模板的指针。但是可以以另一种方式创建函数模板的指针,即引入类模板。因为类模板实例化之后,其中的函数模板就有意义了。但是,这也出现了个问题,就是类模板中的函数模板无法作为函数指针在类外调用,例如在该头文件对应的cpp文件中调用。因此,不得已需要直接在头文件中定义函数体。

#pragma once#include "Task.h"#include <typeinfo>class ParamTem{protected:ParamTem(){};};template <class ReturnType,class P0=ParamTem,class P1=ParamTem,class P2=ParamTem,class P3=ParamTem, class P4=ParamTem,class P5=ParamTem,class P6=ParamTem, class P7=ParamTem>class CMyTask: public CTask,public ParamTem{private:typedef ReturnType (*FuncTem)();typedef ReturnType (*FuncTem0)(P0 p0);typedef ReturnType (*FuncTem1)(P0 p0, P1 p1);typedef ReturnType (*FuncTem2)(P0 p0, P1 p1, P2 p2);typedef ReturnType (*FuncTem3)(P0 p0, P1 p1, P2 p2,P3 p3);typedef ReturnType (*FuncTem4)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4);typedef ReturnType (*FuncTem5)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5);typedef ReturnType (*FuncTem6)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6);typedef ReturnType (*FuncTem7)(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7);FuncTem ft;FuncTem0 ft0;FuncTem1 ft1;FuncTem2 ft2;FuncTem3 ft3;FuncTem4 ft4;FuncTem5 ft5;FuncTem6 ft6;FuncTem7 ft7;P0 p0;P1 p1;P2 p2;P3 p3;P4 p4;P5 p5;P6 p6;P7 p7;public:CMyTask(FuncTem ft){this->ft = ft;}CMyTask(FuncTem0 ft,P0 p0){this->ft0 = ft;this->p0 = p0;}CMyTask(FuncTem1 ft,P0 p0, P1 p1){this->ft1 = ft;this->p0 = p0;this->p1 = p1;}CMyTask(FuncTem2 ft,P0 p0, P1 p1, P2 p2){this->ft2 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;}CMyTask(FuncTem3 ft,P0 p0, P1 p1, P2 p2, P3 p3){this->ft3 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;this->p3 = p3;}CMyTask(FuncTem4 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4){this->ft4 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;this->p3 = p3;this->p4 = p4;}CMyTask(FuncTem5 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5){this->ft5 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;this->p3 = p3;this->p4 = p4;this->p5 = p5;}CMyTask(FuncTem6 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6){this->ft6 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;this->p3 = p3;this->p4 = p4;this->p5 = p5;this->p6 = p6;}CMyTask(FuncTem7 ft,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7){this->ft7 = ft;this->p0 = p0;this->p1 = p1;this->p2 = p2;this->p3 = p3;this->p4 = p4;this->p5 = p5;this->p6 = p6;this->p7 = p7;}virtual void Run(){if(!strcmp(typeid(P0).name(),"class ParamTem")){this->ft();}else if(!strcmp(typeid(P1).name(),"class ParamTem")){this->ft0(this->p0);}else if(!strcmp(typeid(P2).name(),"class ParamTem")){this->ft1(this->p0,this->p1);}else if(!strcmp(typeid(P3).name(),"class ParamTem")){this->ft2(this->p0,this->p1,this->p2);}else if(!strcmp(typeid(P4).name(),"class ParamTem")){this->ft3(this->p0,this->p1,this->p2,this->p3);}else if(!strcmp(typeid(P5).name(),"class ParamTem")){this->ft4(this->p0,this->p1,this->p2,this->p3,this->p4);}else if(!strcmp(typeid(P6).name(),"class ParamTem")){this->ft5(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5);}else if(!strcmp(typeid(P7).name(),"class ParamTem")){this->ft6(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5\,this->p6);}else if(strcmp(typeid(P7).name(),"class ParamTem")){this->ft7(this->p0,this->p1,this->p2,this->p3,this->p4,this->p5\,this->p6,this->p7);}}};
如上只定义了到含8个参数的函数模板,如果你们需要执行的函数的参数可能更多,只需要依葫芦画瓢,添加相应的函数模板即可。

另外定义这个类模板是因为在将函数加入队列貌似不太好办,我也不确定办不了,但是我是没搞出来,所以需要借助对象来保存函数。
这里说明两个地方,首先为什么要定义一个父类,而且,父类的构造函数是protected权限的,这个为了避免其他地方调用这个类生成对象,因为它是MyTask的默认模板参数,默认模板参数则是为了避免参数较少时依然要填满所以的模板参数声明。


#include "StdAfx.h"#include "MyThreadPool.h"CMyThreadPool::CMyThreadPool(int nThreadCount/* =5 */){this->m_nThreadCount=nThreadCount; m_bthreadflag = TRUE;m_hsemaphore = CreateSemaphore(NULL, 0, 5000, NULL);InitializeCriticalSection(&m_csThreadQueue);InitializeCriticalSection(&m_csTaskQueue);m_pThreadItemList=new std::list<ThreadItem*>;m_pTaskList=new std::list<CTask*>;EnterCriticalSection(&m_csThreadQueue);for (int i=0;i<m_nThreadCount;i++){ThreadItem* pItem=new ThreadItem();if (pItem){pItem->pThreadPool=this;pItem->bThreadFlag=TRUE;pItem->hThreadHandle= (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (LPVOID)pItem, 0, &pItem->dwThreadID);printf("创建线程 threadid:%d\n",pItem->dwThreadID);m_pThreadItemList->push_back(pItem);}}LeaveCriticalSection(&m_csThreadQueue);}UINT WINAPI CMyThreadPool::ThreadFunc(LPVOID lpParameter /* = NULL */){//CMyThreadPool* pmyThreadPool = (CMyThreadPool*) lpParameter;ThreadItem *pItem = (ThreadItem*) lpParameter;CTask * m_pTask = NULL;while(pItem->bThreadFlag){WaitForSingleObject(pItem->pThreadPool->m_hsemaphore, INFINITE);EnterCriticalSection(&pItem->pThreadPool->m_csTaskQueue);m_pTask = pItem->pThreadPool->m_pTaskList->front();if(m_pTask){pItem->pThreadPool->m_pTaskList->pop_front();}LeaveCriticalSection(&pItem->pThreadPool->m_csTaskQueue);m_pTask->Run();delete m_pTask;}return NULL;}void CMyThreadPool::StopAllThread(){EnterCriticalSection(&m_csThreadQueue);while (!m_pThreadItemList->empty()){ThreadItem* pThreadItem=m_pThreadItemList->front();if (pThreadItem){//TRACE("结束线程 %d\n",pThreadItem->dwThreadID);printf("结束线程 %d\n",pThreadItem->dwThreadID);pThreadItem->bThreadFlag=FALSE;WaitForSingleObject(pThreadItem->hThreadHandle,INFINITE);m_pThreadItemList->pop_front();delete(pThreadItem);}}LeaveCriticalSection(&m_csThreadQueue);}void CMyThreadPool::schedule(CTask* pTask){EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}CMyThreadPool::~CMyThreadPool(){StopAllThread();DeleteCriticalSection(&m_csThreadQueue);DeleteCriticalSection(&m_csTaskQueue);delete m_pTaskList;delete m_pThreadItemList;}
这是线程池源码,当然正如我在上面所说道的函数模板的问题,在此,其定义的另一个schedule函数需要在头文件中直接定义。
#pragma once#include "MyTask.h"#include <list>#include <process.h>class CMyThreadPool;struct ThreadItem{HANDLE hThreadHandle;       //线程句柄UINT  dwThreadID;          //线程IDBOOL   bThreadFlag;         //线程运行标识CMyThreadPool* pThreadPool;   //属于哪个线程池ThreadItem(){hThreadHandle=NULL;dwThreadID=0;bThreadFlag=FALSE;pThreadPool=NULL;}};class CMyThreadPool{public://CMyThreadPool();CMyThreadPool(int nThreadCount=5);virtual ~CMyThreadPool();static UINT WINAPI ThreadFunc(LPVOID lpParameter = NULL);public:void schedule(CTask* pTask);std::list<ThreadItem*>* GetThreadItemList() {return m_pThreadItemList;};std::list<CTask*>*      GetTaskList() {return m_pTaskList;};void               StopAllThread();void               AdjustSize(int nThreadCount);  //动态调整线程池规模protected://static private:BOOL m_bthreadflag;   int m_nThreadCount;    //线程池中线程的个数HANDLE m_hsemaphore;std::list<ThreadItem*>*  m_pThreadItemList;std::list<CTask*>*       m_pTaskList;CRITICAL_SECTION    m_csThreadQueue;CRITICAL_SECTION    m_csTaskQueue;//Schedule 函数定义public:template<typename ReturnType>void schedule(ReturnType Func()){CTask * pTask = new CMyTask<ReturnType>(Func);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}public:template <typename ReturnType, typename P0>void schedule(ReturnType Func(P0 p0),P0 p0){CTask * pTask = new CMyTask<ReturnType,P0>(Func, p0);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1>void schedule(ReturnType Func(P0 p0, P1 p1),P0 p0, P1 p1){CTask * pTask = new CMyTask<ReturnType,P0,P1>(Func, p0, p1);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2),P0 p0, P1 p1, P2 p2){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2>(Func, p0, p1, p2);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2, typename P3>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3),P0 p0, P1 p1, P2 p2, P3 p3){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3>(Func, p0, p1, p2, p3);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\,typename P4>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4)\,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4>(Func, p0, p1, p2, p3, p4);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\,typename P4, typename P5>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5)\,P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5>(Func, p0, p1, p2, p3, p4, p5);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\,typename P4, typename P5, typename P6>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6),\P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5,P6>(Func, p0, p1, p2, p3, p4, p5, p6);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}template <typename ReturnType, typename P0, typename P1,typename P2, typename P3\,typename P4, typename P5, typename P6,typename P7>void schedule(ReturnType Func(P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7),\P0 p0, P1 p1, P2 p2, P3 p3,P4 p4, P5 p5, P6 p6, P7 p7){CTask * pTask = new CMyTask<ReturnType,P0,P1,P2,P3,P4,P5,P6,P7>(Func, p0, p1, p2, p3, p4, p5, p6,p7);EnterCriticalSection(&m_csTaskQueue);if (m_pTaskList){m_pTaskList->push_back(pTask);}ReleaseSemaphore(this->m_hsemaphore,1,NULL);LeaveCriticalSection(&m_csTaskQueue);}};

这里我用到了一个信号量和一个临界区来保证线程安全,信号量的作用是每有一个执行的对象加入队列,就+1,反之就-1,然后利用WaitforSingleObject来让所有线程等待。临界区就不用说了,这是为了保证MyTask对象的队列的线程安全的。

最后附上线程池源码下载地址http://download.csdn.net/detail/yuguanquan1990/8109379


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑关不了机了怎么办 xp系统关不了机怎么办 灯的开关闭不了怎么办 灯的开关按不动怎么办 灯开关按不动了怎么办 灯的开关摁不动怎么办 微信群500人满了怎么办 作业帮搜不到题目怎么办呢 金融社保卡密码忘了怎么办 工作未完想从国企辞职怎么办 宫腔粘连术后流血多怎么办 宫腔粘连术后一直流血怎么办? cad图框放不下图怎么办 简历假的入职怎么办 脱贫攻坚怎么看怎么办怎么干 吃的下没力气怎么办 恢复留查公示后怎么办 微语简报删了怎么办 小学生未完成作业作为老师怎么办 抽调人员想回原单位怎么办 扫码支付没成功怎么办 成都电表卡丢了怎么办 社保未满15年怎么办 60岁社保没交满15年怎么办 柴油车dpf是亮了怎么办 贴双眼皮贴眼睛肿了怎么办 送孩子赴澳洲家长怎么办签证? 开指过程中发烧怎么办 大水口热流道有料花怎么办 奶奶疼外孙胜过孙子怎么办 吃了有病的鸡怎么办 博士真毕不了业怎么办 35岁博士毕不了业怎么办 跨校考研失败了怎么办 开发商把网签房卖给我该怎么办 cad中命令行没了怎么办 平板玩游戏很卡怎么办 卵巢包块20厘米怎么办 耳机的橡胶破了怎么办 脚被树枝扎破了怎么办 脚被木头扎肿了怎么办