线程池封装设计
1.什么是线程池
线程池就是管理线程的池子,当有任务要处理时,不用频繁创建新线程,而是从池子拿个线程出来处理。当任务执行完,线程并不会被销毁,而是在等待下一个任务。因此可以节省资源,提高响应速度。
你去餐厅吃饭,服务员总是提前洗好盘子,不会等你来打饭的时候才洗盘子,盘子就像是线程池里的线程,你打饭就是要处理的任务。
2、线程池的优点
- 降低资源消耗:通过重复利用现有的线程来执行任务,避免多次创建和销毁线程。
- 提高相应速度:因为省去了创建线程这个步骤,所以在拿到任务时,可以立刻开始执行。
- 提供附加功能:线程池的可拓展性使得我们可以自己加入新的功能,比如说定时、延时来执行某些线程。
互斥量(mutex)封装
class CPThreadMutex
{
public:
CPThreadMutex();
~CPThreadMutex();
bool lock();
bool unlock();
bool trylock();
protected:
pthread_mutex_t m_mutex;
};
CPThreadMutex::CPThreadMutex()
{
if(pthread_mutex_init(&m_mutex,NULL)!=0)
{
perror("pthread mutex init error");
}
}
CPThreadMutex::~CPThreadMutex()
{
if(pthread_mutex_destroy(&m_mutex)!=0)
{
perror("pthread mutex destroy error");
}
}
bool CPThreadMutex::lock()
{
int ret=pthread_mutex_lock(&m_mutex);
if (ret !=0)
{
perror("pthread mutex lock error");
}
return ret==0 ? true: false;
}
bool CPThreadMutex::unlock()
{
int ret=pthread_mutex_unlock(&m_mutex);
if (ret !=0)
{
perror("pthread mutex unlock error");
}
return ret==0 ? true: false;
}
bool CPThreadMutex::trylock()
{
int ret=pthread_mutex_trylock(&m_mutex);
if (ret !=0)
{
perror("pthread mutex trylock error");
}
return ret==0 ? true: false;
}
条件变量(cond)封装
class CPThreadCond :public CPThreadMutex
{
public:
CPThreadCond();
~CPThreadCond();
bool wait();
bool timewait(unsigned int sec);
bool signal();
bool broadcast();
bool isTimeout();
private:
pthread_cond_t m_cond;
bool m_btimeout;
};
```bash
CPThreadCond::CPThreadCond()
:CPThreadMutex(),m_btimeout(false)
{
if(pthread_cond_init(&m_cond,NULL)!=0)
{
perror("pthread cond init error");
}
}
CPThreadCond::~CPThreadCond()
{
if(pthread_cond_destroy(&m_cond)!=0)
{
perror("pthread cond destroy error");
}
}
bool CPThreadCond::wait()
{
int ret=pthread_cond_wait(&m_cond,&m_mutex);
if (ret !=0)
{
perror("pthread cond wait error");
}
return ret==0 ? true: false;
}
bool CPThreadCond::timewait(unsigned int sec)
{
struct timespec abstime;
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += sec;
m_btimeout=false;
int ret=pthread_cond_timedwait(&m_cond,&m_mutex,&abstime);
if (ret==ETIMEDOUT)
{
m_btimeout=true;
return false;
}
else if (ret!=0)
{
perror("pthread cond timedwait error");
}
return ret==0 ? true: false;
}
bool CPThreadCond::signal()
{
int ret=pthread_cond_signal(&m_cond);
if (ret !=0)
{
perror("pthread cond signal error");
}
return ret==0 ? true: false;
}
bool CPThreadCond::broadcast()
{
int ret=pthread_cond_broadcast(&m_cond);
if (ret !=0)
{
perror("pthread cond broadcast error");
}
return ret==0 ? true: false;
}
bool CPThreadCond::isTimeout()
{
return m_btimeout;
}
任务类定义
class CTask
{
public:
CTask(){}
~CTask(){}
virtual int run()=0;
};
class CmyCTask:public CTask
{
public:
CmyCTask(int id) {m_id = id;}
int run()
{
printf("Begin task[%d] \n", m_id);
sleep(3);
printf("End task[%d] \n", m_id);
return 0;
}
int m_id;
protected:
};
线程池类设计
typedef queue<CTask *> queue_task;
class CThreadPool
{
public:
CThreadPool(unsigned int max=100,unsigned int min=10,unsigned int timeout=60);
~CThreadPool();
void addTask(CTask *task); // Add a new task.
void createThread(); // Create a thread.
void createThread(unsigned NumCreate); // Create a num of thread
void destroy(); // Destroy all threads
//private:
static void *taskThread(void *arg);// work thread
unsigned int m_maxcount; // max thread
unsigned int m_mincount; // min thread
unsigned int m_count; // current nums
unsigned int m_idlecount; // idle thread nums
unsigned int m_waitsec; // timeout delay.
queue_task m_taskQueue;
CPThreadCond m_taskCond;
CPThreadCond m_cond;
bool m_bStop;
};
CThreadPool::CThreadPool(unsigned int max/* =100 */,unsigned int min/* =10 */,unsigned int timeout/* =60 */)
{
m_bStop = false;
m_maxcount = max; // max thread
m_mincount = min; // min thread
m_count = 0; // current nums
m_idlecount = 0; // idle thread nums
m_waitsec = timeout; // timeout delay.
// 创建最小数量的线程
m_cond.lock();
for(unsigned i = 0; i < m_mincount; i++)
{
createThread();
}
m_cond.unlock();
}
CThreadPool::~CThreadPool()
{
destroy();
}
void CThreadPool::createThread()
{
pthread_t tid;
if(pthread_create(&tid, NULL, taskThread, this) != 0)
{
perror("pthread_create");
}
else
{
printf("thread[0x%x] create!!\n", (int)pthread_self());
m_count++;
}
}
void CThreadPool::createThread(unsigned NumCreate)
{
// 创建最小数量的线程
m_cond.lock();
for(unsigned i = 0; i < NumCreate && (m_count < m_maxcount-2); i++)
{
createThread();
}
m_cond.unlock();
}
void CThreadPool::addTask(CTask *task)
{
// 1. 添加到任务列表
m_taskCond.lock();
printf("Add task[%d]!\n", ((CmyCTask*)task)->m_id);
m_taskQueue.push(task);
m_taskCond.unlock();
// 2. 通知线程处理
m_cond.lock();
if(m_idlecount > 0)
{
m_cond.signal();
}
else if(m_count < m_maxcount)
{
createThread(); //如果没有空闲线程则尝试再创建线程
}
m_cond.unlock();
}
// Work thread
void * CThreadPool::taskThread(void *arg)
{
pthread_detach(pthread_self()); //设置为自动分离
CThreadPool *pool = (CThreadPool*)arg;
while(1)
{
//1. 取任务做任务
pool->m_taskCond.lock();
while(!pool->m_taskQueue.empty())
{
CTask *ptask = pool->m_taskQueue.front();
pool->m_taskQueue.pop();
pool->m_taskCond.unlock();
// do task
ptask->run();
delete ptask;
pool->m_taskCond.lock();
}
pool->m_taskCond.unlock();
//2. 进入等待处理
pool->m_cond.lock();
if(pool->m_taskQueue.empty())
{
pool->m_idlecount++;
bool bSignal = pool->m_cond.timewait(pool->m_waitsec);
pool->m_idlecount--;
// 判断是否退出或则超时,超时则判断如果超过最小个数的则进行销毁,
// 如果是正常退出则判断是否任务做完了,做完了就销毁
if(((!bSignal && pool->m_count > pool->m_mincount)
|| pool->m_bStop) && pool->m_taskQueue.empty())
{
//清理线程
pool->m_count--;
pool->m_cond.unlock();
if(!bSignal)
printf("thread[0x%x] timeout exit!!\n", (int)pthread_self());
else
printf("thread[0x%x] stop exit!!\n", (int)pthread_self());
pthread_exit(NULL);
}
}
pool->m_cond.unlock();
}
}
void CThreadPool::destroy()
{
m_bStop = true;
while(m_count)
{
m_cond.lock();
m_cond.broadcast();
m_cond.unlock();
sleep(1);
}
}
测试案例:
int main()
{
int taskid = 0;
CThreadPool pool(20, 5, 3);
//pool.start(6);
sleep(1);
for(unsigned i = 0; i < 50; i++)
{
CmyCTask *tsk = new CmyCTask(taskid++);
pool.addTask(tsk);
}
sleep(1);
for(unsigned i = 0; i < 10; i++)
{
CmyCTask *tsk = new CmyCTask(taskid++);
pool.addTask(tsk);
}
sleep(20);
for(unsigned i = 0; i < 50; i++)
{
CmyCTask *tsk = new CmyCTask(taskid++);
pool.addTask(tsk);
}
}
测试结果