1、ThreadPool
#ifndef _ThreadPool_H_
#define _ThreadPool_H_
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#include
#include
#include
#include
#include
#include
using namespace std;
class ThreadTask //任务基类
{
public:
//供线程池调用的虚函数
virtual void DoTask(void* pPara) = 0;
};
class ThreadPool
{
public:
//================================构造及核心外部可调用接口函数==================================
//1.构造函数:创建线程。dwNum 线程池规模
ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0)
{
//初始化2个临界区:线程数据临界区,工作队列(任务队列)临界区
InitializeCriticalSection(&_csThreadVector);
InitializeCriticalSection(&_csTaskQueue);
//创建2个事件、2个信号量:完成事件, 结束通知事件, 工作信号, 删除线程信号
_EventComplete = CreateEvent(0, false, false, NULL);
_EventEnd = CreateEvent(0, true, false, NULL);
_SemaphoreCall = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL);
_SemaphoreDel = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL);
assert(_SemaphoreCall != INVALID_HANDLE_VALUE);
assert(_EventComplete != INVALID_HANDLE_VALUE);
assert(_EventEnd != INVALID_HANDLE_VALUE);
assert(_SemaphoreDel != INVALID_HANDLE_VALUE);
//创建dwNum个工作线程
AdjustSize(dwNum <= 0 ? 4 : dwNum);
}
~ThreadPool()
{
DeleteCriticalSection(&_csTaskQueue);//删除工作队列临界区
//关闭事件、信号量
CloseHandle(_EventEnd);
CloseHandle(_EventComplete);
CloseHandle(_SemaphoreCall);
CloseHandle(_SemaphoreDel);
vector::iterator iter;
//删除所有线程
for (iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++)
{
if (*iter)
delete* iter;
}
DeleteCriticalSection(&_csThreadVector);//删除线程数据临界区
}
//2.创建线程:调整线程池规模
int AdjustSize(int iNum)
{
if (iNum > 0)
{
ThreadItem* pNew;
EnterCriticalSection(&_csThreadVector);
for (int _i = 0; _i < iNum; _i++)
{
_ThreadVector.push_back(pNew = new ThreadItem(this));
assert(pNew);
//创建线程:调用线程函数DefaultTaskProc
pNew->_Handle = CreateThread(NULL, 0, fnDefaultTaskProc, pNew, 0, NULL);
assert(pNew->_Handle);
}
LeaveCriticalSection(&_csThreadVector);
}
else
{
iNum *= -1;
ReleaseSemaphore(_SemaphoreDel, iNum > _lThreadNum ? _lThreadNum : iNum, NULL);
}
return (int)_lThreadNum;
}
//3.调用线程池方法1
void Call(void (*pFunc)(void*), void* pPara = NULL)
{
assert(pFunc);
EnterCriticalSection(&_csTaskQueue);
_TaskQueue.push(new TaskItem(pFunc, pPara));//工作队列中添加任务
LeaveCriticalSection(&_csTaskQueue);
//对指定的信号量(参数一)增加指定的值(参数二:在当前基础上所要增加的值)
ReleaseSemaphore(_SemaphoreCall, 1, NULL);//工作信号 通知线程池有工作
}
//4.调用线程池方法2
inline void Call(ThreadTask* p, void* pPara = NULL)
{
Call(fnCallProc, new CallProcPara(p, pPara));
}
//=====================================================================================
//=========================else:其他外部接口可调用函数==================================
//结束线程池, 并同步等待
bool EndAndWait(DWORD dwWaitTime = INFINITE)
{
SetEvent(_EventEnd);
return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0;//等待 完成事件
}
//结束线程池
inline void End()
{
SetEvent(_EventEnd);//线程池结束事件
}
inline DWORD Size()
{
return (DWORD)_lThreadNum;//线程数
}
inline DWORD GetRunningSize()
{
return (DWORD)_lRunningNum;//运行的线程数
}
bool IsRunning()
{
return _lRunningNum > 0;
}
//=======================================================================================
protected:
//=============================核心内部成员函数===========================================
//1.工作线程()
static DWORD WINAPI fnDefaultTaskProc(LPVOID lpParameter = NULL)
{
ThreadItem* pThread = static_cast(lpParameter);//转型为线程对象指针
assert(pThread);
ThreadPool* pThreadPoolObj = pThread->_pThis;//线程对象中的线程池
assert(pThreadPoolObj);
//1. 增加线程计数
InterlockedIncrement(&pThreadPoolObj->_lThreadNum);
HANDLE hWaitHandle[3];
hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall;//工作信号
hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel;//删除线程信号
hWaitHandle[2] = pThreadPoolObj->_EventEnd;//结束线程信号
TaskItem* pTask = NULL;//用户任务
bool bHasTask;// 是否还有任务
for (;;)
{
DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE);//等待 工作信号, 删除线程信号, 结束线程信号
//1.1 收到并响应删除线程信号 hWaitHandle[1] = _SemaphoreDel
if (wr == WAIT_OBJECT_0 + 1)
break;
//从队列里取得用户任务
EnterCriticalSection(&pThreadPoolObj->_csTaskQueue);
if (bHasTask = !pThreadPoolObj->_TaskQueue.empty())
{
pTask = pThreadPoolObj->_TaskQueue.front();//从队列头取得任务
pThreadPoolObj->_TaskQueue.pop();//从队列中弹出任务
assert(pTask);
}
LeaveCriticalSection(&pThreadPoolObj->_csTaskQueue);
//必须要先从队列取任务,之后才能判断是否有工作:
//1.2收到结束线程信号 确定是否结束线程(结束线程信号 && 没有工作) hWaitHandle[2] = _EventEnd
if (wr == WAIT_OBJECT_0 + 2 && !bHasTask)
break;
if (bHasTask && pTask)//有任务 并且 任务非空
{
//InterlockedIncrement、InterlockedDecrement对整型变量进行原子增加和减少操作
InterlockedIncrement(&pThreadPoolObj->_lRunningNum);//运行的线程数+1
pThread->_dwLastBeginTime = GetTickCount();//记录线程开始时间
pThread->_dwCount++;//运行次数+1
pThread->_fIsRunning = true;
//==========回调主线程中的线程函数===================
pTask->_pFunc(pTask->_pPara); //运行用户任务
//=================================================
//运行任务结束, 释放资源
delete pTask;
pThread->_fIsRunning = false;
InterlockedDecrement(&pThreadPoolObj->_lRunningNum);
}
}
//删除自身结构
EnterCriticalSection(&pThreadPoolObj->_csThreadVector);//线程数据临界
// std::vector _ThreadVector; //线程数据
//线程数据数组中:删除该线程pThread
pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread));
LeaveCriticalSection(&pThreadPoolObj->_csThreadVector);
delete pThread;//删除线程句柄
//2.线程计数减1
InterlockedDecrement(&pThreadPoolObj->_lThreadNum);
if (!pThreadPoolObj->_lThreadNum) //如果线程数为空,说明所有线程结束
SetEvent(pThreadPoolObj->_EventComplete);//完成事件 激活,通知调用者
return 0;
}
//2.调用用户对象虚函数
static void fnCallProc(void* pPara)
{
CallProcPara* cp = static_cast(pPara);//类型转换
assert(cp);
if (cp)//非空
{
cp->_pObj->DoTask(cp->_pPara);//运行用户任务
delete cp;
}
}
//=======================================================================================
//=============================结构体成员变量=============================================
//用户对象结构
struct CallProcPara
{
ThreadTask* _pObj;//用户对象
void* _pPara;//用户参数
CallProcPara(ThreadTask* p, void* pPara) : _pObj(p), _pPara(pPara) {};
};
//用户任务 结构:线程函数指针、参数
struct TaskItem
{
void (*_pFunc)(void*);//线程函数
void* _pPara; //函数参数
TaskItem(void (*pFunc)(void*) = NULL, void* pPara = NULL) : _pFunc(pFunc), _pPara(pPara) {};
};
//线程结构:就是线程 及 线程相关信息
struct ThreadItem
{
HANDLE _Handle; //线程句柄
ThreadPool* _pThis; //线程池的指针
DWORD _dwLastBeginTime; //最后一次运行开始时间
DWORD _dwCount; //运行次数
bool _fIsRunning;//当前线程运行状态
ThreadItem(ThreadPool* pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0), _dwCount(0), _fIsRunning(false) {};
~ThreadItem()
{
if (_Handle)
{
CloseHandle(_Handle);//关闭线程句柄
_Handle = NULL;
}
}
};
//=======================================================================================
//================================成员变量================================================
std::queue _TaskQueue; //任务队列
std::vector _ThreadVector; //线程数据
CRITICAL_SECTION _csThreadVector, _csTaskQueue; //线程数据临界,任务队列临界
HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//结束通知, 完成事件, 任务信号, 删除线程信号
long _lThreadNum, _lRunningNum; //线程数, 运行的线程数
//=======================================================================================
};
#endif //_ThreadPool_H_
2、测试
//ThreadPool tp;
//for (i = 0; i < 100; i++)
// tp.Call(threadfunc);
//
//ThreadPool tp(20);//20为初始线程池规模
//tp.Call(threadfunc, lpPara);
//tp.AdjustSize(50);//增加50
//tp.AdjustSize(-30);//减少30
void threadfunc(void* p)
{
//...
std::cout << "线程ID: " << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
ThreadPool tp(2);
for (int i = 0; i < 20; i++)
{
tp.Call(threadfunc);
}
std::cout << "运行的线程数: " << tp.GetRunningSize() << std::endl;
std::cout << "是否运行: " << tp.IsRunning() << std::endl;
std::cout << "线程池规模: " << tp.Size() << std::endl;
tp.EndAndWait();
std::cout << "线程池规模: " << tp.Size() << std::endl;
std::cout << "运行的线程数: " << tp.GetRunningSize() << std::endl;
std::cout << "是否运行: " << tp.IsRunning() << std::endl;
system("pause");
return 0;
}
结果:
2、