一个简单的线程池,添加任务,做完后销毁线程池
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdbool.h>
#define PTHREAD_MAX 20 //最多有20个线程
#define TASK_FULL_NUM 100 //最多等待100个任务
//任务链表结构体
struct task{
void *(*task_func)(int arg);//任务函数
int task_arg;//任务函数的参数
struct task *next;
};
//线程池
struct pthread_pool{
pthread_t tid[PTHREAD_MAX];//线程号数组
struct task *head;//任务链表的头节点
unsigned int active_pthread_num;//正在运行的线程个数
unsigned int wait_task_num;//正在等待的任务个数
pthread_mutex_t m;//线程池互斥锁
pthread_cond_t v;//线程池条件变量
bool shutdown;//线程销毁标志位 flase:不销毁 true:销毁
};
void *time_sec()//计时线程
{
static int time=0;
while(1)
{
printf(" sec:%d\n",time++);
sleep(1);
}
}
void *f(int arg)//任务函数
{
printf("%#x running\n",(unsigned int)pthread_self());
while(arg)
{
arg--;
sleep(1);
}
printf("%#x end\n",(unsigned int)pthread_self());
}
//死锁清理函数
void cleanup(void *arg)
{
printf("%#x cleanup \n",(unsigned int)pthread_self());
struct pthread_pool *pool = (struct pthread_pool *)arg;
pthread_mutex_unlock(&pool->m);
}
void *func(void *arg)//线程执行的函数
{
struct pthread_pool *pool = (struct pthread_pool *)arg;
struct task *p =NULL;
while(1)
{
//=======注册死锁退出函数====
pthread_cleanup_push(cleanup,(void *)pool);
//=======加上互斥锁========
pthread_mutex_lock(&pool->m);
//由于没有正在等待的任务,释放互斥锁,开始等待条件变量
if(pool->wait_task_num == 0 && pool->shutdown == false)
pthread_cond_wait(&pool->v,&pool->m);
//唤醒条件变量可能是任务链表增加,也可能是因为销毁了线程
//如果是销毁线程引起的,那么就结束线程
if(pool->shutdown == true)
{
pthread_exit(NULL);//调用死锁注册函数
}
//从任务链表中拿取任务执行,因为任务链表不为NULL,那么至少有一个任务
p = pool->head->next;
pool->head->next = p->next;
//======释放互斥锁========
pthread_mutex_unlock(&pool->m);
//======解除死锁注册函数===
pthread_cleanup_pop(0);
//*******在处理任务过程中禁止响应线程取消*******
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
//将正在等待的任务个数-1
pool->wait_task_num--;
//执行任务函数
p->task_func(p->task_arg);
//释放任务节点
free(p);
//*******在释放掉所有资源以后,可以取消线程*******
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
}
pthread_exit(NULL);
}
//初始化线程池
struct pthread_pool* pthread_pool_init()
{
struct pthread_pool *pool = malloc(sizeof(struct pthread_pool));
if(pool == NULL)
{
perror("pool malloc failed");
exit(-1);
}
//任务链表头节点的初始化---整个链表为NULL
pool->head = malloc(sizeof(struct task));
if(pool->head == NULL)
{
perror("pool->head malloc failed");
exit(-1);
}
pool->head->next = NULL;
//初始化完以后,一个正在运行线程都没有
pool->active_pthread_num = 0;
//初始化完以后,一个任务都没有
pool->wait_task_num = 0;
//初始化互斥锁
pthread_mutex_init(&pool->m,NULL);
//初始化条件变量
pthread_cond_init(&pool->v,NULL);
//将线程池销毁标志位置为flase---不销毁
pool->shutdown = false;
return pool;
}
//创建线程-->向线程池添加线程
int pthread_pool_add(struct pthread_pool *pool,int addnum)
{
//添加0个线程
if(addnum == 0)
return 0;//只是结束当前线程
int i=0;
int added=0;
for(i = pool->active_pthread_num;
i<PTHREAD_MAX && i< pool->active_pthread_num + addnum;
i++)
{
//创建线程
if( pthread_create( &pool->tid[i],NULL, func,(void *)pool) != 0)
{
perror("pthread_create faield");
break;
}
//成功添加的线程个数
added++;
}
//更新正在运行的线程个数
pool->active_pthread_num += added;
return added;
}
//任务添加函数
int pool_add_task(struct pthread_pool *pool,void *(*f)(int arg),int arg )
{
//任务链表中已经等待的任务个数已经达到最大
if(pool->wait_task_num == TASK_FULL_NUM)
{
printf("task list full\n");
return -1;
}
//创建任务节点
struct task *node = malloc(sizeof(struct task));
if(node == NULL)
{
perror("task node malloc failed");
exit(-1);
}
//将需要添加到任务链表中的函数和参数进行赋值
node->task_func = f;
node->task_arg = arg;
node->next = NULL;
//==========加互斥锁============
pthread_mutex_lock(&pool->m);
//把新任务加入到链表的末尾
struct task *p = pool->head;
while(p->next != NULL)
p=p->next;
p->next = node;
//==========释放互斥锁==========
pthread_mutex_unlock(&pool->m);
//每当有任务加入到链表中,让正在等待的任务链表个数数值++
pool->wait_task_num++;
//向一个线程发送信号,让它开始执行
pthread_cond_signal(&pool->v);
return 0;
}
//销毁线程池
int pool_delete(struct pthread_pool *pool)
{
//将线程池销毁标志位置为true---销毁
pool->shutdown = true;
//向所有线程发起唤醒条件变量
pthread_cond_broadcast(&pool->v);
//如果需要立即销毁所有线程,那么向所有线程发起取消信号
//并且等待线程结束
//---->强制取消线程可能会引起死锁q
//---->万一任务执行函数有malloc或者其他申请资源,需要让他自己释放
int i;
for(i=0; i<pool->active_pthread_num; i++ )
{
pthread_cancel(pool->tid[i]);
printf("tid[%d]=%#x\n",i,(unsigned int)pool->tid[i]);
pthread_join(pool->tid[i],NULL);
}
//销毁任务链表
struct task *p = pool->head->next;
while(p != NULL)
{
pool->head->next = p->next;
free(p);
p = pool->head->next;
}
free(pool->head);
//销毁线程池
free(pool);
printf("pthrad_pool end\n");
}
int main()
{
//开启计时线程
pthread_t tid;
pthread_create(&tid,NULL,time_sec,NULL);
struct pthread_pool *pool = pthread_pool_init();
//线程池添加2个线程
pthread_pool_add(pool,2);
sleep(2);
//添加任务
pool_add_task(pool,f,3);
pool_add_task(pool,f,6);
sleep(1);
//线程池添加2个线程
pthread_pool_add(pool,1);
sleep(4);
pool_add_task(pool,f,5);
pool_add_task(pool,f,3);
sleep(3);
//销毁线程池
pool_delete(pool);
//暂停
pause();
return 0;
}