线程池
线程池是一种对线程进行管理的一种机制,其线程创建释放和获取任务均由线程池来完成,如果一个应用需要频繁的创建线程处理任务,如果不对线程加以现存限制,当任务爆发时可能会因为内存不足造成瘫痪,另外线程的创建和释放需要成本,线程数量增多后线程的调度也会变慢。因此当每个线程处理时间特别段或者需要对线程的数量加以限制时可以使用线程池。
在这实现一个简单的固定数量的线程加任务队列的一个线程池
#include <iostream>
#include <pthread.h>
#include <queue>
#include <unistd.h>
#define THREAD_AMOUNT_MAX 5
class Task
{
public:
Task(int num = 0)
:num_(num)
{}
Task(const Task & t)
{
num_ = t.num_;
}
void SetNum(int num)
{
num_ = num;
}
void run()
{
sleep(1);
std::cout << "[" << pthread_self() << "]:" <<num_ << std::endl;
}
private:
int num_;
};
class ThreadPool
{
public:
ThreadPool(int num = THREAD_AMOUNT_MAX)
:thread_amount_(num)
,hangup_amount_(0)
{
pthread_mutex_init(&mutex_, NULL);
pthread_cond_init(&cond_, NULL);
}
void InitThreadPool()
{
for(int i = 0; i < thread_amount_; ++i)
{
pthread_t tid_;
pthread_create(&tid_, NULL, start_rounte, this);
}
}
void TaskPush(Task & task)
{
LockQueue();
if(hangup_amount_ > 0)
{
RouseOneThread();
}
task_queue_.push(task);
UnLockQueue();
}
~ThreadPool()
{
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&cond_);
}
private:
void TaskPop(Task & task)
{
task = task_queue_.front();
task_queue_.pop();
}
void RouseOneThread()
{
pthread_cond_signal(&cond_);
}
void LockQueue()
{
pthread_mutex_lock(&mutex_);
}
void UnLockQueue()
{
pthread_mutex_unlock(&mutex_);
}
bool TaskIsEmpty()
{
return task_queue_.empty();
}
static void * start_rounte(void * arg)
{
ThreadPool *tp = static_cast<ThreadPool *>(arg);
pthread_detach(pthread_self());
for(;;)
{
tp->LockQueue();
//使用while因为此时如果有一个线程刚好获得锁然后任务队列
//添加了任务并且唤醒了另一个线程,会造成两个线程共同取
//任务
while(tp->TaskIsEmpty())
{
tp->ThreadHangup();
}
Task task_;
tp->TaskPop(task_);
tp->UnLockQueue();
task_.run();
}
}
void ThreadHangup()
{
++hangup_amount_;
pthread_cond_wait(&cond_, &mutex_);
--hangup_amount_;
}
private:
std::queue<Task> task_queue_;
pthread_mutex_t mutex_;
pthread_cond_t cond_;
int thread_amount_;
int hangup_amount_;
};
#include "thread_pool.hpp"
void test()
{
ThreadPool * tp = new ThreadPool();
tp->InitThreadPool();
Task t(0);
for(int i = 1; i < 100; ++i)
{
t.SetNum(i);
tp->TaskPush(t);
sleep(1);
}
while(1)
{
;
}
}
int main()
{
test();
return 0;
}