线程池
- 线程池=线程安全队列+一大堆的线程(消费线程)
- 线程池中的线程,都是同一种角色的线程,每一个线程都执行同样的入口函数
- 线程安全队列中的元素,保存待处理的数据和处理数据的方式
如何让相同入口函数的线程,处理不同的请求
- switch case:处理大量不同的需求的时候,比较麻烦
- 向线程池抛入数据的时候,将处理该数据的函数一起抛入(函数地址),线程池当中的线程只需要调入传入的处理函数处理传入的数据即可
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <queue>
//线程池=线程安全队列+一大堆的线程
//线程安全队列的元素:数据+处理数据的函数地址
//
//
#define THREADCOUNT 4
//函数指针
typedef void* (*Handler_t)(int);
//定义队列元素类型
class ThreadTask
{
public:
ThreadTask(int data,Handler_t handler)
{
data_=data;
handler_=handler;
}
~ThreadTask()
{
}
//使用函数,处理数据
void Run()
{
handler_(data_);
}
private:
int data_;
Handler_t handler_;
};
//线程池
class ThreadPool
{
public:
ThreadPool()
{
//队列的大小
capacity_=10;
//线程池中线程的大小
thread_capacity_=THREADCOUNT;
//互斥和同步
pthread_mutex_init(&lock_,NULL);
pthread_cond_init(&cond_,NULL);
//创建线程
bool is_create=ThreadCreate();
if(!is_create)
{
printf("Threadpool Create Thread Failed\n");
exit(1);
}
IsExit=false;
cur_thread_count_=THREADCOUNT;
}
~ThreadPool()
{
}
bool Push(ThreadTask* tt)
{
pthread_mutex_lock(&lock_);
if(IsExit)
{
pthread_mutex_unlock(&lock_);
return false;
}
que_.push(tt);
pthread_mutex_unlock(&lock_);
//插入数据之后,通知线程池当中的线程(消费)
pthread_cond_signal(&cond_);
return true;
}
bool Pop(ThreadTask** tt)
{
*tt=que_.front();
que_.pop();
return true;
}
void ThreadJoin()
{
for(int i=0;i<THREADCOUNT;i++)
{
pthread_join(tid_[i],NULL);
}
}
void ThreadExit()
{
for(int i=0;i<THREADCOUNT;i++)
{
pthread_cancel(tid_[i]);
}
}
void ThreadPoolClear()
{
//标志位
pthread_mutex_lock(&lock_);
IsExit=true;
pthread_mutex_unlock(&lock_);
if(cur_thread_count_>0)
{
pthread_cond_broadcast(&cond_);
}
}
private:
//加static修饰,函数传递的参数没有this指针
static void* THreadstart(void* arg)
{
ThreadPool* tp=(ThreadPool*)arg;
while(1)
{
//从队列中获取数据进行消费
pthread_mutex_lock(&tp->lock_);
ThreadTask* tt;
while(tp->que_.empty())
{
if(tp->IsExit)
{
tp->cur_thread_count_--;
pthread_mutex_unlock(&tp->lock_);
//退出
pthread_exit(NULL);
}
//调用条件变量等待接口
pthread_cond_wait(&tp->cond_,&tp->lock_);
}
tp->Pop(&tt);
pthread_mutex_unlock(&tp->lock_);
//调用队列当中元素提供的函数,去处理数据
tt->Run();
delete tt;
}
}
bool ThreadCreate()
{
for(int i=0;i<THREADCOUNT;i++)
{
int ret=pthread_create(&tid_[i],NULL,THreadstart,(void*)this);
if(ret!=0)
{
perror("pthread_create");
return false;
}
}
return true;
}
private:
std::queue<ThreadTask*> que_;
size_t capacity_;
//互斥
pthread_mutex_t lock_;
//同步
pthread_cond_t cond_;
//线程当中初始化的时候线程数量
size_t thread_capacity_;
//线程池中具体还有多少线程
size_t cur_thread_count_;
//保存线程池当中的线程的标识符
pthread_t tid_[THREADCOUNT];
//标志是否可以退出
bool IsExit;
};
void* DealData(int data)
{
printf("消费的数据是 %d\n",data);
return NULL;
}
int main()
{
ThreadPool* tp=new ThreadPool();
for(int i=1;i<=50;i++)
{
ThreadTask* tt=new ThreadTask(i,DealData);
tp->Push(tt);
}
sleep(15);
//等待线程池中线程退出
tp->ThreadPoolClear();
tp->ThreadJoin();
delete tp;
return 0;
}