下面将从线程的设计思路及线程池的使用进行说明。
线程池管理主体设计思路是:
1、封装线程管理对象 MyThread,用于线程创建、线程开启、线程睡眠、任务绑定等操作。
2、封装空闲线程栈管理对象IdleThreadContainer,用于空闲线程栈的维护管理等操作。空闲的线程放于此栈中。
3、封装忙碌线程队列管理对象BusyThreadContainer,用于忙碌线程队列的维护及管理等操作。忙碌的线程放于此队列中。
4、封装任务管理对象MyTask,用于线程函数等任务信息的设置操作。
5、封装任务队列管理对象TaskContainer,用于任务队列的管理及维护等操作。
6、封装线程池管理对象CThreadPoolExp,用于线程池线程创建、线程任务添加、线程任务调度、忙碌线程及空闲线程队列维护管理等操作。开启一个管理线程,对线程任务调度进行管理。
#include <windows.h>
class Task;
class CBaseThreadPool;
class MyThread
{
public:
MyThread(CBaseThreadPool *pBaseThreadPool);
virtual ~MyThread(void);
public:
bool StartMyThread();
bool CloseMyThread();
bool SuspendMyThread();
bool ResumeMyThread();
bool AssignTask(Task *pTask);
bool StartTask();
static unsigned _stdcall ThreadProc(LPVOID lParam);
private:
static void ReleaseMemory(MyThread *pThread);
public:
DWORD m_iThreadID;
HANDLE m_hThread;
CBaseThreadPool *m_pBaseThreadPool;
private:
bool m_bIsExit;
HANDLE m_hEvent;
Task *m_pTask;
};
#include "mythread.h"
#include <process.h>
#include "task.h"
#include "ThreadPoolExp.h"
MyThread::MyThread(CBaseThreadPool *pBaseThreadPool)
: m_iThreadID(0)
, m_hThread(NULL)
, m_pBaseThreadPool(pBaseThreadPool)
, m_bIsExit(true)
, m_hEvent(NULL)
, m_pTask(NULL)
{
m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
MyThread::~MyThread(void)
{
CloseHandle(m_hEvent);
}
bool MyThread::StartTask()
{
if ( NULL == m_pTask )
return false;
return ResumeMyThread();
}
unsigned _stdcall MyThread::ThreadProc(LPVOID lParam)
{
MyThread *pThread = static_cast<MyThread *>(lParam);
if ( NULL == pThread )
return 1;
DWORD ret = WAIT_FAILED;
while (!pThread->m_bIsExit)
{
ret = WaitForSingleObject(pThread->m_hEvent, INFINITE);
if ( WAIT_OBJECT_0 == ret )
{
if ( pThread->m_pTask )
{
pThread->m_pTask->TaskProc();
//任务完成清除任务释放资源
ReleaseMemory(pThread);
//线程挂起,根据当前是否有新任务来判断是否将当前线程放入空闲线程栈
pThread->m_pBaseThreadPool->SwitchActiveThread(pThread);
}
}
}
return 0;
}
void MyThread::ReleaseMemory(MyThread *pThread)
{
if(!pThread)
{
return;
}
if(pThread->m_pTask)
{
delete(pThread->m_pTask);
pThread->m_pTask = NULL;
}
}
bool MyThread::StartMyThread()
{
if ( !m_bIsExit )
return true;
m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (LPVOID)this, 0, NULL);
if ( NULL == m_hThread )
return false;
m_iThreadID = GetThreadId(m_hThread);
m_bIsExit = false;
return true;
}
bool MyThread::CloseMyThread()
{
if ( NULL == m_hThread )
return true;
m_bIsExit = true;
m_pTask = NULL;
ResumeMyThread();
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
return true;
}
bool MyThread::SuspendMyThread()
{
if ( NULL == m_hThread )
return false;
ResetEvent(m_hEvent);
return true;
}
bool MyThread::ResumeMyThread()
{
if ( NULL == m_hThread )
return false;
SetEvent(m_hEvent);
return true;
}
bool MyThread::AssignTask(Task *pTask)
{
if ( NULL == pTask )
return false;
m_pTask = pTask;
return true;
}
#include <vector>
#include <stack>
#include "typedef.h"
class MyThread;
class IdleThreadContainer
{
public:
IdleThreadContainer(void);
virtual ~IdleThreadContainer(void);
public:
MyThread* Pop();
bool Push(MyThread *pThread);
bool IsEmpty();
bool Clear();
int GetSize();
private:
std::stack<MyThread *> m_ThreadStack;
CMyLock m_AutoLock;
};
#include "idlethreadcontainer.h"
#include "mythread.h"
IdleThreadContainer::IdleThreadContainer(void)
: m_AutoLock(CMyLock())
{
}
IdleThreadContainer::~IdleThreadContainer(void)
{
}
MyThread* IdleThreadContainer::Pop()
{
if ( IsEmpty() )
return NULL;
MyThread *pThread = NULL;
CMyAutoLock autoLock(&m_AutoLock);
if ( m_ThreadStack.empty() )
return NULL;
pThread = m_ThreadStack.top();
pThread->ResumeMyThread();
m_ThreadStack.pop();
return pThread;
}
bool IdleThreadContainer::Push(MyThread *pThread)
{
if ( NULL == pThread )
return false;
CMyAutoLock autoLock(&m_AutoLock);
pThread->SuspendMyThread();
m_ThreadStack.push(pThread);
return true;
}
bool IdleThreadContainer::IsEmpty()
{
CMyAutoLock autoLock(&m_AutoLock);
bool ret = m_ThreadStack.empty();
return ret;
}
bool IdleThreadContainer::Clear()
{
if ( IsEmpty() )
return true;
CMyAutoLock autoLock(&m_AutoLock);
MyThread *pThread = NULL;
while (!m_ThreadStack.empty())
{
pThread = m_ThreadStack.top();
pThread->CloseMyThread();
delete pThread;
m_ThreadStack.pop();
}
return true;
}
int IdleThreadContainer::GetSize()
{
CMyAutoLock autoLock(&m_AutoLock);
int iSize = m_ThreadStack.size();
return iSize;
}
#include <list>
#include "typedef.h"
class MyThread;
class BusyThreadContainer
{
public:
BusyThreadContainer(void);
virtual ~BusyThreadContainer(void);
public:
bool AddThread(MyThread *pThread);
bool RemoveThread(MyThread *pThread);
bool IsEmpty();
bool Clear();
int GetSize();
private:
std::list<MyThread *> m_ThreadList;
CMyLock m_AutoLock;
};
#include "busythreadcontainer.h"
#include "mythread.h"
BusyThreadContainer::BusyThreadContainer(void)
: m_AutoLock(CMyLock())
{
}
BusyThreadContainer::~BusyThreadContainer(void)
{
}
bool BusyThreadContainer::AddThread(MyThread *pThread)
{
if ( NULL == pThread )
return false;
CMyAutoLock autoLock(&m_AutoLock);
m_ThreadList.push_back(pThread);
return true;
}
bool BusyThreadContainer::RemoveThread(MyThread *pThread)
{
if ( NULL == pThread || IsEmpty() )
return false;
CMyAutoLock autoLock(&m_AutoLock);
if ( IsEmpty() )
return false;
m_ThreadList.remove(pThread);
return true;
}
bool BusyThreadContainer::IsEmpty()
{
CMyAutoLock autoLock(&m_AutoLock);
bool ret = m_ThreadList.empty();
return ret;
}
bool BusyThreadContainer::Clear()
{
if ( IsEmpty() )
return true;
CMyAutoLock autoLock(&m_AutoLock);
std::list<MyThread *>::iterator it = m_ThreadList.begin();
while ( it != m_ThreadList.end() )
{
(*it)->CloseMyThread();
delete *it;
++it;
}
m_ThreadList.clear();
return true;
}
int BusyThreadContainer::GetSize()
{
CMyAutoLock autoLock(&m_AutoLock);
int iSize = m_ThreadList.size();
return iSize;
}
#include "typedef.h"
namespace
{
enum PRIORITY
{
MIN = 1, NORMAL = 25, MAX = 50
};
}
typedef bool (*pTaskFun)(LPVOID lParam);
class Task
{
public:
Task():m_iTaskID(0) {}
Task(int id):m_iTaskID(id) {}
Task(int id, pTaskFun TaskFunAddress, LPVOID lParam)
: m_iTaskID(id)
, m_pTaskFun(TaskFunAddress)
, m_lParam(lParam)
{
}
virtual ~Task() {}
public:
int GetID() { return m_iTaskID; }
virtual bool SetTaskInfo(int id, pTaskFun TaskFunAddress, LPVOID lParam) = 0;
virtual bool TaskProc() = 0;
virtual bool TaskProc(pTaskFun TaskFunAddress, LPVOID lParam) = 0;
protected:
int m_iTaskID;
pTaskFun m_pTaskFun;
LPVOID m_lParam;
};
class MyTask
: public Task
{
public:
MyTask() {}
MyTask(int id);
MyTask(int id, pTaskFun TaskFunAddress, LPVOID lParam);
virtual ~MyTask(void);
public:
virtual bool SetTaskInfo(int id, pTaskFun TaskFunAddress, LPVOID lParam);
virtual bool TaskProc();
virtual bool TaskProc(pTaskFun TaskFunAddress, LPVOID lParam);
};
#include "task.h"
MyTask::MyTask(int id)
: Task(id)
{
}
MyTask::MyTask(int id, pTaskFun TaskFunAddress, LPVOID lParam)
: Task(id, TaskFunAddress, lParam)
{
}
MyTask::~MyTask(void)
{
}
bool MyTask::SetTaskInfo(int id, pTaskFun TaskFunAddress, LPVOID lParam)
{
if ( NULL == TaskFunAddress || NULL == lParam )
return false;
m_iTaskID = id;
m_pTaskFun = TaskFunAddress;
m_lParam = lParam;
return true;
}
bool MyTask::TaskProc()
{
if ( NULL == m_pTaskFun || NULL == m_lParam )
return false;
return m_pTaskFun(m_lParam);
}
bool MyTask::TaskProc(pTaskFun TaskFunAddress, LPVOID lParam)
{
if ( NULL == TaskFunAddress || NULL == lParam )
return false;
return TaskFunAddress(lParam);
}
#include <deque>
#include "typedef.h"
class Task;
class TaskContainer
{
public:
TaskContainer(void);
virtual ~TaskContainer(void);
public:
Task* Pop();
bool Push(Task *pTask);
bool PushFront(Task *pTask);
bool IsEmpty();
bool Clear();
int GetSize();
private:
std::deque<Task *> m_TaskQueue;
CMyLock m_AutoLock;
};
#include "taskcontainer.h"
#include "task.h"
TaskContainer::TaskContainer(void)
: m_AutoLock(CMyLock())
{
}
TaskContainer::~TaskContainer(void)
{
}
Task* TaskContainer::Pop()
{
if ( IsEmpty() )
return NULL;
Task *pTask = NULL;
CMyAutoLock autoLock(&m_AutoLock);
if ( m_TaskQueue.empty() )
return NULL;
pTask = m_TaskQueue.front();
m_TaskQueue.pop_front();
return pTask;
}
bool TaskContainer::Push(Task *pTask)
{
if ( NULL == pTask )
return false;
CMyAutoLock autoLock(&m_AutoLock);
m_TaskQueue.push_back(pTask);
return true;
}
bool TaskContainer::PushFront(Task *pTask)
{
if ( NULL == pTask )
return false;
CMyAutoLock autoLock(&m_AutoLock);
m_TaskQueue.push_front(pTask);
return true;
}
bool TaskContainer::IsEmpty()
{
CMyAutoLock autoLock(&m_AutoLock);
bool ret = m_TaskQueue.empty();
return ret;
}
bool TaskContainer::Clear()
{
CMyAutoLock autoLock(&m_AutoLock);
m_TaskQueue.clear();
return true;
}
int TaskContainer::GetSize()
{
CMyAutoLock autoLock(&m_AutoLock);
int iSize = m_TaskQueue.size();
return iSize;
}
#include <Windows.h>
#include <process.h>
#include "typedef.h"
#include "taskcontainer.h"
#include "idlethreadcontainer.h"
#include "busythreadcontainer.h"
class Task;
class MyThread;
class CBaseThreadPool
{
public:
CBaseThreadPool() {}
virtual ~CBaseThreadPool() {}
public:
virtual int SetThreadNum(int iThreadNum) = 0;
virtual bool AddTask(Task *pTask, TASK_PRIORITY priority) = 0;
virtual Task* GetNewTask() = 0;
virtual MyThread* GetIdleThread() = 0;
virtual bool SwitchActiveThread(MyThread *pThread) = 0;
virtual bool StartThreadPool() = 0;
virtual bool DestroyThreadPool() = 0;
virtual bool IsExit() = 0;
};
class CThreadPoolExp
: public CBaseThreadPool
{
public:
CThreadPoolExp(void);
virtual ~CThreadPoolExp(void);
public:
virtual int SetThreadNum(int iThreadNum);
virtual bool AddTask(Task *pTask, TASK_PRIORITY priority);
virtual Task* GetNewTask();
virtual MyThread* GetIdleThread();
virtual bool SwitchActiveThread(MyThread *pThread);
virtual bool StartThreadPool();
virtual bool DestroyThreadPool();
virtual bool IsExit();
public:
static unsigned _stdcall ThreadProc(LPVOID lParam);
private:
bool SuspendThread();
bool ResumeThread();
bool ManageThreads();
private:
bool m_bIsExit;
bool m_bIsResumed; //线程是否被唤起
int m_iThreadNum;
HANDLE m_hThread;
HANDLE m_hSemaphore; //调度线程唤起信号
TaskContainer m_TaskQueue;
IdleThreadContainer m_IdleThreadSTask;
BusyThreadContainer m_BusyThreadList;
};
#include "threadpoolexp.h"
#include "mythread.h"
CThreadPoolExp::CThreadPoolExp(void)
: m_bIsExit(true)
, m_bIsResumed(false)
, m_iThreadNum(0)
, m_hThread(NULL)
, m_hSemaphore(NULL)
{
m_hSemaphore = CreateEvent(NULL, TRUE, FALSE, NULL);
}
CThreadPoolExp::~CThreadPoolExp(void)
{
DestroyThreadPool();
CloseHandle(m_hSemaphore);
}
bool CThreadPoolExp::AddTask(Task *pTask, TASK_PRIORITY priority)
{
if ( NULL == pTask )
return false;
if ( TASK_PRIORITY_HIGH == priority )
{
m_TaskQueue.PushFront(pTask);
}
else
{
m_TaskQueue.Push(pTask);
}
if ( !m_TaskQueue.IsEmpty() && !m_IdleThreadSTask.IsEmpty())
{
ResumeThread(); //唤起调度线程
}
return true;
}
bool CThreadPoolExp::SwitchActiveThread(MyThread *pThread)
{
if ( m_TaskQueue.IsEmpty() )
{
m_BusyThreadList.RemoveThread(pThread);
m_IdleThreadSTask.Push(pThread);
}
else
{
Task *pTask = NULL;
pTask = m_TaskQueue.Pop();
if ( NULL == pTask )
{
m_BusyThreadList.RemoveThread(pThread);
m_IdleThreadSTask.Push(pThread);
return true;
}
// OutputDebugString("pThread->AssignTask(pTask)\r\n");
pThread->AssignTask(pTask);
pThread->StartTask();
}
return true;
}
unsigned _stdcall CThreadPoolExp::ThreadProc(LPVOID lParam)
{
CThreadPoolExp *pThreadPool = static_cast<CThreadPoolExp *>(lParam);
pThreadPool->ManageThreads();
return 0;
}
bool CThreadPoolExp::ManageThreads()
{
DWORD ret = WAIT_FAILED;
while ( true )
{
ret = WaitForSingleObject(m_hSemaphore, INFINITE);
if(WAIT_OBJECT_0 == ret)
{
if ( m_bIsExit )
{
return false;
}
if ( m_TaskQueue.IsEmpty() )
{
SuspendThread();
}
else
{
MyThread *pThread = GetIdleThread();
if ( NULL == pThread )
{
SuspendThread();
continue;
}
Task *pTask = NULL;
pTask = GetNewTask();
if ( NULL == pTask )
{
m_IdleThreadSTask.Push(pThread);
continue;
}
m_BusyThreadList.AddThread(pThread);
pThread->AssignTask(pTask);
pThread->StartTask();
}
}
}
return true;
}
bool CThreadPoolExp::SuspendThread()
{
if(NULL == m_hThread)
{
return false;
}
if(!m_bIsResumed) //已被睡眠则返回
{
return true;
}
bool isSucceed = ResetEvent(m_hSemaphore);
if(isSucceed)
{
m_bIsResumed = false;
}
return true;
}
bool CThreadPoolExp::ResumeThread()
{
if(NULL == m_hThread)
{
return false;
}
if(m_bIsResumed)
{
return true;
}
bool isSucceed = SetEvent(m_hSemaphore);
if(isSucceed)
{
m_bIsResumed = true;
}
return true;
}
MyThread* CThreadPoolExp::GetIdleThread()
{
if ( m_IdleThreadSTask.IsEmpty() )
return NULL;
return m_IdleThreadSTask.Pop();
}
Task* CThreadPoolExp::GetNewTask()
{
if ( m_TaskQueue.IsEmpty() )
return NULL;
Task *pTask = NULL;
pTask = m_TaskQueue.Pop();
return pTask;
}
int CThreadPoolExp::SetThreadNum(int iThreadNum)
{
m_iThreadNum = iThreadNum;
return m_iThreadNum;
}
bool CThreadPoolExp::StartThreadPool()
{
if ( 0 == m_iThreadNum || !IsExit() )
return false;
m_bIsExit = false;
m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, this, 0, NULL);
if ( NULL == m_hThread )
{
m_bIsExit = true;
return false;
}
for ( int i = 0; i < m_iThreadNum; ++i )
{
MyThread *pThread = new MyThread(this);
pThread->StartMyThread();
m_IdleThreadSTask.Push(pThread);
}
return true;
}
bool CThreadPoolExp::DestroyThreadPool()
{
if ( IsExit() )
return true;
m_bIsExit = true;
Sleep(50);
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
ResetEvent(m_hSemaphore);
m_TaskQueue.Clear();
m_IdleThreadSTask.Clear();
m_BusyThreadList.Clear();
return true;
}
bool CThreadPoolExp::IsExit()
{
return m_bIsExit;
}
#include <Windows.h>
#include <QString>
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
typedef long long int64_Cam;
typedef int int32_Cam;
typedef unsigned int uint32_Cam;
typedef unsigned long long uint64_Cam;
typedef struct ThreadInfo
{
ThreadInfo(QString sql, QString path, LPVOID pObject)
:m_sSql(sql)
,m_sFilePath(path)
,m_pObject(pObject)
{
}
QString m_sSql; //数据导出数据库查询语句
QString m_sFilePath; //导出文件存储路径
LPVOID m_pObject; //窗口信息输出对象
}THREAD_INFO;
enum TASK_PRIORITY
{
TASK_PRIORITY_NORMAL,
TASK_PRIORITY_HIGH
};
class Task;
class CMyLock
{
public:
CMyLock() {
InitializeCriticalSectionAndSpinCount(&m_cs, 4000);
}
~CMyLock() {
DeleteCriticalSection(&m_cs);
}
void Lock() {
EnterCriticalSection(&m_cs);
//OutputDebugString("EnterCriticalSection(&m_cs);\r\n");
}
void UnLock() {
LeaveCriticalSection(&m_cs);
//OutputDebugString("LeaveCriticalSection(&m_cs);\r\n");
}
private:
CRITICAL_SECTION m_cs;
};
class CMyAutoLock
{
public:
CMyAutoLock(CMyLock *pLock) : m_pLock(pLock) {
if ( m_pLock )
m_pLock->Lock();
}
~CMyAutoLock() {
if ( m_pLock )
m_pLock->UnLock();
}
private:
CMyLock *m_pLock;
};
#endif // TYPEDEF_H
线程池的使用:
线程函数声明:
static bool funRun(LPVOID lParam); //需线程处理的任务
线程函数定义:
bool MyScene::funRun(LPVOID lParam)
{
if(NULL == lParam)
{
return false;
}
THREAD_INFO *pInfo = static_cast<THREAD_INFO*>(lParam);
if(pInfo)
{
qDebug()<<pInfo->m_sSql;
qDebug()<<pInfo->m_sFilePath;
MyScene *pMySence = static_cast<MyScene*>(pInfo->m_pObject);
if(pMySence)
{
return;
}
emit pMySence->threadStarted();
//do something
delete(pInfo);//资源回收
pInfo = NULL;
emit pMySence->threadFinished();
}
}
线程池的使用:
//线程池测试
QString fixSql("");
QString fixFilePath("");
for(int i = 0; i < 10; ++i)
{
fixSql = tr("fixSql at:%1").arg(i);
fixFilePath = tr("fixFilePath at:%1").arg(i);
THREAD_INFO *pInfo = new THREAD_INFO(fixSql, fixFilePath, this);
MyTask *pTask = new MyTask;
pTask->SetTaskInfo(i, funRun, pInfo);
ThreadPool::g_cThreadPoolExp->AddTask(pTask, TASK_PRIORITY_NORMAL);
}