线程池-pthread_pool
- 含义:顾名思义,线程池是集中管理多个线程的工具,在其中包含着多个线程的存储以及对线程任务的处理。
- 源代码:
1)任务序列:
通过回调函数call_back指定线程所要执行的任务。
在线程池中用struct job*head,tail链接形成任务序列。
struct jobs{
void* (*call_back)(void* i);
void* i;
struct jobs* next;
};
2)线程池结构体:
struct thread_pool
{
int pthread_num;//线程数目
int queue_max_num;//任务队列的最大数目
int queue_cur_num;//任务队列的当前数目
struct jobs* head;//任务队列头指针
struct jobs* tail;//任务队列尾指针
pthread_t *pthreads;//线程数组
pthread_mutex_t mutex;
pthread_cond_t queue_empty;//队列为空
pthread_cond_t queue_not_empty;//队列不为空(任务队列有任务)
pthread_cond_t queue_not_full;//队列不为满
int pool_close;
};
3)线程池初始化函数
返回一个空的线程池指针new
struct thread_pool* pool_init(int pthread_num,int queue_max_num)
{
struct thread_pool *new=(struct thread_pool*)malloc(sizeof(struct thread_pool));
new->pthread_num=pthread_num;
new->queue_max_num=queue_max_num;
new->queue_cur_num=0;
new->head=new->tail=NULL;
new->pthreads=malloc(sizeof(pthread_t)*pthread_num);
for(int i=0;i<pthread_num;i++)
{
pthread_create(&new->pthreads[i],NULL,pool_function,(void*)new);
// 每个线程默认执行pool_function函数 并将线程池传入
}
pthread_mutex_init(&new->mutex,NULL);
pthread_cond_init(&new->queue_empty,NULL);
pthread_cond_init(&new->queue_not_empty,NULL);
pthread_cond_init(&new->queue_not_full,NULL);
new->pool_close=0;
if(new==NULL){
printf("init erro\n");
return 0;
}
else return new;
}
4)添加任务函数函数
向线程池任务队列中添加任务,function为函数指针即线程要执行的函数。
void add_job(struct thread_pool* pool,void*(*function)(void*),void* i)
{
pthread_mutex_lock(&pool->mutex);
//如果超过最大值则阻塞中not_full条件上
while (pool->queue_cur_num==pool->queue_max_num)
{
pthread_cond_wait(&pool->queue_not_full,&pool->mutex);
}
//初始化job
struct jobs* job=malloc(sizeof(struct jobs));
if(job==NULL){
printf("job malloc erro");
_exit(0);
}
job->call_back=function;
job->i=i;
//将job添加到pool中的链表
if(pool->head==NULL&&pool->tail==NULL)//如果job为第一个
{
job->next=NULL;
pool->head=pool->tail=job;
}
else{
pool->tail->next=job;
pool->tail=job;
}
pool->queue_cur_num++;
pthread_mutex_unlock(&pool->mutex);
if(pool->queue_cur_num!=0)
pthread_cond_signal(&pool->queue_not_empty);
}
5)loop:每个线程循环执行的函数
//不断的执行任务队列中的任务
void* pool_function(void* i)
{
struct thread_pool* pool=(struct thread_pool*)i;
while(1){
pthread_mutex_lock(&pool->mutex);
while(pool->queue_cur_num==0&&pool->pool_close==0)
{
pthread_cond_wait(&pool->queue_not_empty,&pool->mutex);//刚创建所有的线程都会阻塞在not_empty这个条件上
}
//当等待队列不为空时,执行其中的一个job
struct jobs *pjob=pool->head;
pool->queue_cur_num--;
//执行完一个程序后唤醒阻塞中not_full上的线程
if(pool->queue_cur_num<pool->queue_max_num)
pthread_cond_signal(&pool->queue_not_full);
pool->head=pool->head->next;
//到最后head会为nuLL而tail为最后一个job
if(pool->head==NULL)
pool->tail=NULL;
pthread_mutex_unlock(&pool->mutex);
(*(pjob->call_back))(pjob->i);//执行第一个job的函数
free(pjob);
if(pool->queue_cur_num==0&&pool->pool_close==0)
pthread_cond_signal(&pool->queue_empty);
}
}
6)供测试用的任务函数
void* work(void* i)
{
printf("i do it\n");
}
void* print1(void* i)
{
printf("1\n");
}
7)线程池销毁
释放内存,销毁锁
void destroy(struct thread_pool* pool)
{
pthread_mutex_lock(&pool->mutex);
if(pool->queue_cur_num!=0)
pthread_cond_wait(&pool->queue_empty,&pool->mutex);
struct jobs* temp;
// struct jobs* cur=pool->head;
while(pool->head!=pool->tail)
{
temp=pool->head;
pool->head=pool->head->next;
free(temp);
}
free(pool->head);
free(pool->tail);
for(int i=0;i<pool->pthread_num;i++)
{
pthread_join(pool->pthreads[i],NULL);
}
pthread_mutex_destroy(&pool->mutex);
pthread_cond_destroy(&pool->queue_empty);
pthread_cond_destroy(&pool->queue_not_empty);
pool->pool_close=1;//关闭标志
}
8)main函数
int main()
{
struct thread_pool *pool=pool_init(5,10);//5个线程 10个job
add_job(pool,work,NULL);
add_job(pool,work,NULL);
add_job(pool,print1,NULL);
add_job(pool,print1,NULL);
add_job(pool,print1,NULL);
add_job(pool,print1,NULL);
add_job(pool,print1,NULL);
sleep(4);
destroy(pool);
while(1);
return 0;
}
3.执行结果:
与所预想结果对应,调用了2次work函数,5次print1函数,因为只有5个线程,所以应该是成功了.