线程池,就是事先创建好多那个线程,抽象成一个装有多个线程的池子,或者说是缓冲区,用来处理外部的操作请求。
首先得弄明白一个问题:为什么需要创建线程池。
我个人的看法:在多线程编程当中,处理不同的请求,往往是放在一个线程当中,但是当请求数到达一定程度时,不管理这些线程容易造成程序混乱。另外一个优点就是节省了创建线程的时间,这在大量快速请求的情况下,性能方面显得尤为突出。
线程池其实就是一个线程的缓冲区,首先我们先创建好一个任务队列,然后在创建多个线程的集合,具体的抽象按自己的需要而定。然后就是多个线程调度任务队列,每当线程处于空闲时就会调用一个任务,让自己处于忙状态。如果所有线程都处于忙,则新增的任务进行排队,等待调度。
任务队列的抽象:一个链式队列,数据是任务的处理函数以及函数的入参。
线程池的抽象:任务队列的头指针,当前的任务数,最大的线程数目
代码如下:
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <pthread.h>
#include <unistd.h>
#include <iostream>
//define task queue
typedef struct _TASK_QUEUE
{
void *(*event)(void *);
void *arg;
struct _TASK_QUEUE *next;
}TASK_QUEUE;
//static void *process(void *arg);
class threadpool
{
private:
unsigned long m_ulMaxThreadNum;
unsigned long m_ulSize; // current task queue length
TASK_QUEUE *m_pTaskHead;//task list's head
TASK_QUEUE *m_pTaskTail;//task list's tail
pthread_t *m_pthreadBase; //pthread id
pthread_mutex_t m_queueMutex;
pthread_cond_t m_queueCond;
bool m_closeFlag;
public:
threadpool();
~threadpool();
void initPool(unsigned long num);
void destroyPool();
void addTask(void *(*event)(void *), void *arg);
void rmCurrTask();
static void *process(void *arg);
};
#endif
#include "threadpool.h"
pthread_attr_t SetPthreadAttr(int more_mem)
{
pthread_attr_t attr;
int stacksize;
int ret;
ret = pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
stacksize = (PTHREAD_STACK_MIN + more_mem);
ret = pthread_attr_setstacksize(&attr, stacksize);
return attr;
}
threadpool::threadpool()
{
m_pTaskHead = NULL;
m_pTaskTail = NULL;
m_pthreadBase = NULL;
m_ulMaxThreadNum = 0;
m_ulSize = 0;
m_closeFlag = 1;
pthread_mutex_init(&m_queueMutex, NULL);
pthread_cond_init(&m_queueCond, NULL);
}
threadpool::~threadpool()
{
}
void threadpool::initPool(unsigned long num)
{
m_ulMaxThreadNum = num;
m_closeFlag = 0;
pthread_mutex_init(&m_queueMutex, NULL);
pthread_cond_init(&m_queueCond, NULL);
m_pthreadBase = new pthread_t [m_ulMaxThreadNum];
pthread_t pthreadId;
for(int i = 0; i < num; ++i)
{
pthread_create(&pthreadId, NULL, process, this);
m_pthreadBase[i] = pthreadId;
printf("create a thread.\n");
}
}
void threadpool::destroyPool()
{
m_closeFlag = 1;
pthread_cond_broadcast(&m_queueCond);
for(int i = 0; i < m_ulMaxThreadNum; ++i)
{
pthread_join(m_pthreadBase[i], NULL);
}
pthread_mutex_destroy(&m_queueMutex);
pthread_cond_destroy(&m_queueCond);
delete []m_pthreadBase;
m_pthreadBase = NULL;
m_ulMaxThreadNum = 0;
TASK_QUEUE *pTmp = NULL;
while(m_pTaskHead)
{
pTmp = m_pTaskHead;
m_pTaskHead = m_pTaskHead->next;
free(pTmp);
}
m_pTaskTail = NULL;
}
void threadpool::addTask(void *(*event)(void *), void *arg)
{
TASK_QUEUE *pstNewTask = new TASK_QUEUE;
memset(pstNewTask, 0, sizeof(TASK_QUEUE));
pstNewTask->event = event;
pstNewTask->arg = arg;
pstNewTask->next = NULL;
pthread_mutex_lock(&m_queueMutex);
if(!m_pTaskHead)
{
m_pTaskHead = pstNewTask;
m_pTaskHead->next = NULL;
m_pTaskTail = m_pTaskHead;
m_ulSize++;
}
else
{
m_pTaskTail->next = pstNewTask;
m_pTaskTail = pstNewTask;
m_ulSize++;
} pthread_cond_signal(&m_queueCond); pthread_mutex_unlock(&m_queueMutex);
//printf("Add a task to task queue\n");
}
void threadpool::rmCurrTask()
{
TASK_QUEUE *pTmp = NULL;
if(!m_pTaskHead)
{
printf("TaskQueue is empty.\n");
return;
}
pTmp = m_pTaskHead;
m_pTaskHead = m_pTaskHead->next;
m_ulSize--;
delete pTmp;
//printf("Remove a task from queue.\n");
}
void *threadpool::process(void *arg)
{
threadpool *pcPool = (threadpool *)arg;
TASK_QUEUE stTaskProc;
while(1)
{
pthread_mutex_lock(&pcPool->m_queueMutex);
if(pcPool->m_closeFlag)
{
pthread_mutex_unlock(&pcPool->m_queueMutex);
printf("Exit.\n");
pthread_exit(NULL);
}
if(!pcPool->m_pTaskHead)
{
pthread_cond_wait(&pcPool->m_queueCond, &pcPool->m_queueMutex);
printf("Recv a signal.\n");
//pthread_mutex_unlock(&pcPool->m_queueMutex);
}
if(pcPool->m_pTaskHead)
{
memset(&stTaskProc, 0, sizeof(TASK_QUEUE));
memcpy(&stTaskProc, pcPool->m_pTaskHead, sizeof(TASK_QUEUE));
//run event
pcPool->rmCurrTask();
pthread_mutex_unlock(&pcPool->m_queueMutex);
stTaskProc.event(stTaskProc.arg);
}
else
pthread_mutex_unlock(&pcPool->m_queueMutex);
}
pthread_exit(NULL);
}
#if 0
void taskevent(void *arg)
{
printf("%^&*()_\n");
}
void *hello(void *arg)
{
threadpool *pcPool = (threadpool *)arg;
while(1)
{
pcPool->addTask((void* (*)(void*))taskevent, NULL);
printf("hello kitty.\n");
sleep(1);
}
printf("Never should be here.\n");
}
int main()
{
threadpool pool;
pool.initPool(10);
sleep(1);
pthread_attr_t attr;
attr = SetPthreadAttr(10240);
pthread_t pthreadTmp;
pthread_create(&pthreadTmp, &attr, hello, &pool);
while(1)
{
sleep(1);
}
return 0;
}
#endif