pthread库实现一个简单的任务池
类关系图:
说明:
1:TaskManager类管理Task类,Task类是一个纯虚类;
2:ThreadManager类管理Thread类,Thread类封装pthread库的相关线程函数;
3:Thread类通过TaskManager类获取需要执行的任务;
4:ThreadManager类中包含一个TaskManager用于管理需要其管理线程执行的Task;
5:UserTask是用户继承Task类而来的用户自己的任务类,最后线程池中运行的任务就是UserTask。
该交代的都交代了,现在上代码。^-^
Task.h
自己封装了一个锁类,GuardLock.h
TaskManager.h
TaskManager.cpp
Thread.h
Thread.cpp
ThreadManager.h
ThreadManager.cpp
main.cpp
makefile
运行程序后程序的输出:
ThreadManager::ThreadManager*0xbfdf52d4
TaskManager::TaskManager*0x8599008
Thread::Thread*0x8599030
Thread::Thread*0x85990f0
Thread::Thread*0x85991b0
MyTask::MyTask*0x8599270
MyTask::MyTask*0x8599290
MyTask::MyTask*0x85992b0
MyTask::MyTask*0x85992d0
MyTask::MyTask*0x85992f0
MyTask::MyTask*0x8599310
MyTask::MyTask*0x8599330
MyTask::MyTask*0x8599350
MyTask::MyTask*0x8599370
MyTask::MyTask*0x8599390
MyTask::MyTask*0x85993b0
MyTask::MyTask*0x85993d0
MyTask::MyTask*0x85993f0
MyTask::MyTask*0x8599410
MyTask::MyTask*0x8599430
MyTask::MyTask*0x8599450
MyTask::MyTask*0x8599470
MyTask::MyTask*0x8599490
MyTask::MyTask*0x85994b0
MyTask::MyTask*0x85994d0
thread id: 3058080576
thread id: 3074865984
thread id: 3066473280
MyTask::~MyTask#0x8599270
thread id: 3058080576
MyTask::~MyTask#0x8599290
thread id: 3074865984
MyTask::~MyTask#0x85992b0
thread id: 3066473280
MyTask::~MyTask#0x85992d0
thread id: 3058080576
MyTask::~MyTask#0x85992f0
thread id: 3074865984
MyTask::~MyTask#0x8599310
thread id: 3066473280
MyTask::~MyTask#0x8599330
thread id: 3058080576
MyTask::~MyTask#0x8599350
thread id: 3074865984
MyTask::~MyTask#0x8599370
thread id: 3066473280
MyTask::~MyTask#0x85993b0
thread id: 3074865984
MyTask::~MyTask#0x8599390
thread id: 3058080576
MyTask::~MyTask#0x85993f0
thread id: 3074865984
MyTask::~MyTask#0x85993d0
thread id: 3066473280
MyTask::~MyTask#0x8599410
thread id: 3058080576
MyTask::~MyTask#0x8599430
thread id: 3074865984
MyTask::~MyTask#0x8599450
thread id: 3066473280
MyTask::~MyTask#0x8599470
thread id: 3058080576
MyTask::~MyTask#0x8599490
MyTask::~MyTask#0x85994b0
MyTask::~MyTask#0x85994d0
Thread::~Thread#0x8599030
Thread::~Thread#0x85990f0
Thread::~Thread#0x85991b0
ThreadManager::~ThreadManager#0xbfdf52d4
TaskManager::~TaskManager#0x8599008
谢谢。
说明:
1:TaskManager类管理Task类,Task类是一个纯虚类;
2:ThreadManager类管理Thread类,Thread类封装pthread库的相关线程函数;
3:Thread类通过TaskManager类获取需要执行的任务;
4:ThreadManager类中包含一个TaskManager用于管理需要其管理线程执行的Task;
5:UserTask是用户继承Task类而来的用户自己的任务类,最后线程池中运行的任务就是UserTask。
该交代的都交代了,现在上代码。^-^
Task.h
/**********************
* author: zhanghang
* date: 2016.02.27
* file: Task.h
* usage: this is the pure virtual base class of the task in the task pool
***********************/
#ifndef _TASK_H
#define _TASK_H
#define TIMES_OF_SLEEP_ONE_SEC 1500000
class Task
{
public:
Task(){};
virtual ~Task(){};
virtual void Process() = 0;
// all the delay operations should use this function
void Delay(int sec)
{
for(int i=0; i<sec; ++i)
{
for(int j=0; j<TIMES_OF_SLEEP_ONE_SEC; ++j)
{
}
}
}
};
#endif
自己封装了一个锁类,GuardLock.h
/************************
* author: zhanghang
* date: 2016.02.27
* file: GuardLock.h
* usage: this class to lock a code scope
************************/
#ifndef _GUARD_LOCK_H
#define _GUARD_LOCK_H
#include <pthread.h>
#include <iostream>
class GuardLock
{
public:
GuardLock(pthread_mutex_t *pMutex):m_pMutex(pMutex)
{
pthread_mutex_lock(m_pMutex);
}
~GuardLock()
{
pthread_mutex_unlock(m_pMutex);
}
private:
pthread_mutex_t *m_pMutex;
};
#endif
TaskManager.h
/************************
* author: zhanghang
* date: 2016.02.27
* file: TaskManager.h
* usage: this class is to manage the tasks
***********************/
#ifndef _TASK_MANAGER_H
#define _TASK_MANAGER_H
#include <pthread.h>
#include <list>
class Task;
class TaskManager
{
public:
TaskManager();
~TaskManager();
void AddTask(Task *pTask);
void DeleteAllTask();
int GetTaskNum();
Task *GetATask();
private:
std::list<Task *> m_TaskList;
pthread_mutex_t m_AccTaskListMutex;
};
#endif
TaskManager.cpp
/************************
* author: zhanghang
* date: 2016.02.27
* file: TaskManager.cpp
* usage: this class is to manage the tasks
***********************/
#include "GuardLock.h"
#include "TaskManager.h"
#include "Task.h"
#include <iostream>
TaskManager::TaskManager()
{
std::cout << "TaskManager::TaskManager*" << (void *)this << std::endl;
}
TaskManager::~TaskManager()
{
std::cout << "TaskManager::~TaskManager#" << (void *)this << std::endl;
if(m_TaskList.size() > 0)
{
DeleteAllTask();
}
}
void TaskManager::AddTask(Task *pTask)
{
GuardLock lock(&m_AccTaskListMutex);
if(NULL != pTask)
{
m_TaskList.push_back(pTask);
}
}
void TaskManager::DeleteAllTask()
{
GuardLock lock(&m_AccTaskListMutex);
std::list<Task *>::iterator taskItr = m_TaskList.begin();
while(m_TaskList.end() != taskItr)
{
delete *taskItr;
++taskItr;
}
m_TaskList.clear();
}
int TaskManager::GetTaskNum()
{
return m_TaskList.size();
}
Task *TaskManager::GetATask()
{
GuardLock lock(&m_AccTaskListMutex);
Task *pTask = NULL;
std::list<Task *>::iterator taskBeg = m_TaskList.begin();
if(m_TaskList.end() != taskBeg)
{
pTask = (*taskBeg);
m_TaskList.erase(taskBeg);
}
return pTask;
}
Thread.h
/************************
* author: zhanghang
* date: 2016.02.27
* file: Thread.h
* usage: this class is to new a thread
***********************/
#ifndef _THREAD_H
#define _THREAD_H
#include <pthread.h>
#define TIMES_OF_SLEEP_ONE_SEC 1500000
class Task;
class TaskManager;
// the entrance of the new thread
void *ThreadMain(void *pArg);
class Thread
{
public:
Thread(TaskManager &taskManager);
~Thread();
int Run();
int Stop();
bool IsFree();
// because there is one cnacel point in the sleep func
// so i write my own delay func
void Delay(int sec);
friend void *ThreadMain(void *pArg);
private:
bool m_IsFree;
bool m_ExitFlag;
Task *m_pTask;
TaskManager &m_TaskMgr;
pthread_t m_ThreadID;
};
#endif
Thread.cpp
/************************
* author: zhanghang
* date: 2016.02.27
* file: Thread.cpp
* usage: this class is to new a thread
***********************/
#include "Thread.h"
#include "Task.h"
#include "TaskManager.h"
#include <iostream>
Thread::Thread(TaskManager &taskMgr)
: m_IsFree(true), m_ExitFlag(false), m_pTask(NULL), m_TaskMgr(taskMgr), m_ThreadID(0)
{
std::cout << "Thread::Thread*" << (void *)this << std::endl;
}
Thread::~Thread()
{
std::cout << "Thread::~Thread#" << (void *)this << std::endl;
if(!m_ExitFlag)
{
m_ExitFlag = true;
}
}
int Thread::Run()
{
return pthread_create(&m_ThreadID, NULL, ThreadMain, this);
}
int Thread::Stop()
{
m_ExitFlag = true;
void *pRet = NULL;
pthread_cancel(m_ThreadID);
return pthread_join(m_ThreadID, &pRet);
}
bool Thread::IsFree()
{
return m_IsFree;
}
void Thread::Delay(int sec)
{
for(int i=0; i<sec; ++i)
{
for(int j=0; j<TIMES_OF_SLEEP_ONE_SEC; ++j)
{
}
}
}
// thre entrance of thread
void *ThreadMain(void *pArg)
{
if(NULL == pArg)
{
return NULL;
}
// set the cancel state to enable
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
// set the cancel type to run to next cnacel point
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
Thread &rThread = *((Thread *)pArg);
while(!rThread.m_ExitFlag)
{
rThread.m_pTask = rThread.m_TaskMgr.GetATask();
// there is no task
if(NULL == rThread.m_pTask)
{
rThread.m_IsFree = true;
//sleep(1); // do not use sleep function, there is some cancel point in the function
rThread.Delay(1);
continue;
}
rThread.m_IsFree = false;
// the mission
rThread.m_pTask->Process();
// clear the task room
delete rThread.m_pTask;
rThread.m_pTask = NULL;
// set a cancel point
pthread_testcancel();
}
}
ThreadManager.h
/************************
* author: zhanghang
* date: 2016.02.07
* file: ThreadManager.h
* usage: this class is to manage the threads
*******************************/
#ifndef _THREAD_MANAGER_H
#define _THREAD_MANAGER_H
#include <list>
class Task;
class Thread;
class TaskManager;
class ThreadManager
{
public:
ThreadManager();
~ThreadManager();
int StartThreads(int num);
int StopThreads();
void AddTask(Task *);
int GetTaskNum();
int GetThreadNum();
bool CreateTaskManager();
private:
std::list<Thread *> m_ThreadList;
TaskManager *m_pTaskMgr;
};
#endif
ThreadManager.cpp
/*********************
* author: zhanghang
* date: 2016.02.27
* file: ThreadManager.cpp
* usage: this class is to manage the task pool
*************************/
#include <iostream>
#include "ThreadManager.h"
#include "Thread.h"
#include "Task.h"
#include "TaskManager.h"
ThreadManager::ThreadManager(): m_pTaskMgr(NULL)
{
std::cout << "ThreadManager::ThreadManager*" << (void *)this << std::endl;
}
ThreadManager::~ThreadManager()
{
std::cout << "ThreadManager::~ThreadManager#" << (void *)this << std::endl;
if(m_ThreadList.size() > 0)
{
StopThreads();
}
if(NULL != m_pTaskMgr)
{
delete m_pTaskMgr;
m_pTaskMgr = NULL;
}
}
bool ThreadManager::CreateTaskManager()
{
if(NULL == m_pTaskMgr)
{
m_pTaskMgr = new TaskManager();
if(NULL == m_pTaskMgr)
{
return false;
}
}
return true;
}
// return the truely thread num
int ThreadManager::StartThreads(int num)
{
if(!CreateTaskManager())
{
return 0;
}
int result = 0;
for(int i=0; i<num; ++i)
{
Thread *pThread = NULL;
pThread = new Thread(*m_pTaskMgr);
result = pThread->Run();
if(0 != result)
{
std::cout << "one thread started failed! error code: " << result << std::endl;
continue;
}
m_ThreadList.push_back(pThread);
}
return m_ThreadList.size();
}
// return the num of threads that left
int ThreadManager::StopThreads()
{
std::list<Thread *>::iterator threadItr = m_ThreadList.begin();
int result = 0;
while(m_ThreadList.end() != threadItr)
{
result = (*threadItr)->Stop();
if(0 != result)
{
std::cout << "one thread stopped failed! error code: " << result << std::endl;
++threadItr;
continue;
}
// delete the thread
delete *threadItr;
m_ThreadList.erase(threadItr++);
}
// the left thread
return m_ThreadList.size();
}
void ThreadManager::AddTask(Task *pTask)
{
if(!CreateTaskManager())
{
return;
}
m_pTaskMgr->AddTask(pTask);
}
int ThreadManager::GetTaskNum()
{
if(!CreateTaskManager())
{
return 0;
}
return m_pTaskMgr->GetTaskNum();
}
int ThreadManager::GetThreadNum()
{
return m_ThreadList.size();
}
main.cpp
/*************
* author: zhanghang
* date: 2016.02.27
* file: main.cpp
* usage: this is a demo of taskpool
********************************/
#include "ThreadManager.h"
#include "Task.h"
#include <iostream>
#include <unistd.h>
#define THREAD_NUM 3
// this is the task
class MyTask : public Task
{
public:
MyTask()
{
std::cout << "MyTask::MyTask*" << (void *)this << std::endl;
}
~MyTask()
{
std::cout << "MyTask::~MyTask#" << (void *)this << std::endl;
}
void Process()
{
std::cout << "thread id: " << pthread_self() << std::endl;
Delay(1);
}
};
int main(int argc, char **argv)
{
ThreadManager threadMgr;
threadMgr.StartThreads(THREAD_NUM);
for(int i=0; i<20; ++i)
{
MyTask *pMyTask = new MyTask();
Task *pTask = (Task *) pMyTask;
// add task
threadMgr.AddTask(pTask);
}
sleep(4);
threadMgr.StopThreads();
return 1;
}
makefile
main: ThreadMgr Thread TaskMgr
g++ -o main main.cpp ThreadManager.o Thread.o TaskManager.o -lpthread -g
ThreadMgr:
g++ -c ThreadManager.cpp ThreadManager.h Thread.h TaskManager.h Task.h -g
Thread:
g++ -c Thread.cpp Thread.h Task.h TaskManager.h -g
TaskMgr:
g++ -c TaskManager.cpp TaskManager.h GuardLock.h Task.h -g
clean:
rm *.o
运行程序后程序的输出:
ThreadManager::ThreadManager*0xbfdf52d4
TaskManager::TaskManager*0x8599008
Thread::Thread*0x8599030
Thread::Thread*0x85990f0
Thread::Thread*0x85991b0
MyTask::MyTask*0x8599270
MyTask::MyTask*0x8599290
MyTask::MyTask*0x85992b0
MyTask::MyTask*0x85992d0
MyTask::MyTask*0x85992f0
MyTask::MyTask*0x8599310
MyTask::MyTask*0x8599330
MyTask::MyTask*0x8599350
MyTask::MyTask*0x8599370
MyTask::MyTask*0x8599390
MyTask::MyTask*0x85993b0
MyTask::MyTask*0x85993d0
MyTask::MyTask*0x85993f0
MyTask::MyTask*0x8599410
MyTask::MyTask*0x8599430
MyTask::MyTask*0x8599450
MyTask::MyTask*0x8599470
MyTask::MyTask*0x8599490
MyTask::MyTask*0x85994b0
MyTask::MyTask*0x85994d0
thread id: 3058080576
thread id: 3074865984
thread id: 3066473280
MyTask::~MyTask#0x8599270
thread id: 3058080576
MyTask::~MyTask#0x8599290
thread id: 3074865984
MyTask::~MyTask#0x85992b0
thread id: 3066473280
MyTask::~MyTask#0x85992d0
thread id: 3058080576
MyTask::~MyTask#0x85992f0
thread id: 3074865984
MyTask::~MyTask#0x8599310
thread id: 3066473280
MyTask::~MyTask#0x8599330
thread id: 3058080576
MyTask::~MyTask#0x8599350
thread id: 3074865984
MyTask::~MyTask#0x8599370
thread id: 3066473280
MyTask::~MyTask#0x85993b0
thread id: 3074865984
MyTask::~MyTask#0x8599390
thread id: 3058080576
MyTask::~MyTask#0x85993f0
thread id: 3074865984
MyTask::~MyTask#0x85993d0
thread id: 3066473280
MyTask::~MyTask#0x8599410
thread id: 3058080576
MyTask::~MyTask#0x8599430
thread id: 3074865984
MyTask::~MyTask#0x8599450
thread id: 3066473280
MyTask::~MyTask#0x8599470
thread id: 3058080576
MyTask::~MyTask#0x8599490
MyTask::~MyTask#0x85994b0
MyTask::~MyTask#0x85994d0
Thread::~Thread#0x8599030
Thread::~Thread#0x85990f0
Thread::~Thread#0x85991b0
ThreadManager::~ThreadManager#0xbfdf52d4
TaskManager::~TaskManager#0x8599008
谢谢。