浅谈线程池:
线程池是一个使用多线程来处理一个可并行执行的任务。
可并行执行的任务就是一个任务可以拆分很多部分,每个部分可以同时进行处理,所有部分处理完后整个任务也就处理完成。(相当于生产一个玩具,可以拆开很多部分,每个部件不一定是按着顺序生产,但是只要生产完成了,这个玩具就完成了)
线程池内部会启动多个线程,每个线程都可以执行独立的工作,互相之间可以联系,也可以没有联系。
线程中通过线程的互斥和同步技术来实现任务之间互相配合
线程池内部组件
//最大等待任务数
#define MAX_WAITING_TASKS 2000
//最大活动线程数
#define MAX_ACTIVE_THREADS 20
//任务链表节点
typedef struct task{
void *(*task_func)(void *arg);//任务处理函数
void *arg;//任务处理函数的参数
struct task *next;//单链表
}task_t;
//线程池
typedef struct thread_pool{
pthread_mutex_t lock;//互斥锁
pthread_cond_t cond;//条件变量
task_t *task_list;//任务链表
int shutdown;//结束标志
unsigned int max_waiting_tasks;//最大等待任务数
unsigned int current_waiting_tasks;//当前等待任务数
unsigned int max_active_threads;//最大活动线程数
unsigned int current_active_threads;//当前活动线程数
pthread_t id[MAX_ACTIVE_THREADS];
}thread_pool_t;
线程函数与线程退出处理函数
//线程退出处理函数
void func(void *arg)
{
printf("线程%lu退出处理!\n",pthread_self());
//解锁
pthread_mutex_unlock((pthread_mutex_t *)arg);
}
//线程函数
void *start_routine(void *arg)
{
task_t *p = NULL;
thread_pool_t *thread_pool = (thread_pool_t *)arg;
pthread_cleanup_push(func,&thread_pool->lock);
while(1){
//加锁
pthread_mutex_lock(&thread_pool->lock);
//如果无任务可执行,也没有退出标志,睡眠等待唤醒
if(thread_pool->current_waiting_tasks==0&&thread_pool->shutdown==0){
pthread_cond_wait(&thread_pool->cond,&thread_pool->lock);
}
//没有任务,但是有退出标志
if(thread_pool->current_waiting_tasks==0&&thread_pool->shutdown!=0){
pthread_exit(NULL);
}
//有任务,执行任务
//不允许退出
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
p = thread_pool->task_list->next;//链表中取出一个任务
if(!p){
printf("task_list error!\n");
pthread_mutex_unlock(&thread_pool->lock);
continue;
}
//从链表中删掉任务
thread_pool->task_list->next = p->next;
//当前等待任务数-1
thread_pool->current_waiting_tasks--;
//解锁
pthread_mutex_unlock(&thread_pool->lock);
//执行任务处理函数
p->task_func(p->arg);
//释放p
free(p);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
}
pthread_exit(NULL);
pthread_cleanup_pop(0);
}
线程池相关对外接口
- 初始化线程池
参数:
thread_pool:线程池
thread_num:线程池线程数量
返回值:
成功返回0,失败返回-1
int init_thread_pool(thread_pool_t *thread_pool,int threads_num)
{
if(threads_num>MAX_ACTIVE_THREADS){
printf("too many threads_num!\n");
return -1;
}
//初始化互斥锁和条件变量
pthread_mutex_init(&thread_pool->lock,NULL);
pthread_cond_init(&thread_pool->cond,NULL);
//初始化任务链表
thread_pool->task_list = (task_t *)malloc(sizeof(task_t));
if(!thread_pool->task_list){
perror("malloc");
return -1;
}
thread_pool->task_list->next = NULL;
//初始化结束标志
thread_pool->shutdown = 0;//不结束
//最大等待任务数
thread_pool->max_waiting_tasks = MAX_WAITING_TASKS;
//当前等待任务数
thread_pool->current_waiting_tasks = 0;
//最大活动线程数
thread_pool->max_active_threads = MAX_ACTIVE_THREADS;
//当前活动线程数
thread_pool->current_active_threads = threads_num;
//创建线程
int i = 0;
for(i=0;i<threads_num;i++){
pthread_create(&thread_pool->id[i],NULL,start_routine,(void *)thread_pool);
printf("%lu线程开始!\n",thread_pool->id[i]);
}
return 0;
}
- 添加任务
参数:
thread_pool:线程池
task_func(void arg) :线程函数
arg:传入线程函数的参数
返回值:
成功返回0,失败返回-1
int add_task(thread_pool_t *thread_pool,void *(*task_func)(void *arg),void *arg)
{
if(thread_pool->current_waiting_tasks>=thread_pool->max_waiting_tasks){
printf("too many tasks!\n");
return -1;
}
//构造节点
task_t *new_task = (task_t *)malloc(sizeof(task_t));
if(!new_task){
perror("malloc");
return -1;
}
//初始化节点
new_task->task_func = task_func;
new_task->arg = arg;
//将节点插入链表
//加锁
pthread_mutex_lock(&thread_pool->lock);
//插入链表尾部
task_t *tail = thread_pool->task_list;
while(tail->next)
tail = tail->next;
tail->next = new_task;
new_task->next = NULL;
//等待任务数+1
thread_pool->current_waiting_tasks++;
//解锁
pthread_mutex_unlock(&thread_pool->lock);
//唤醒一个等待的线程
pthread_cond_signal(&thread_pool->cond);
return 0;
}
- 添加线程
参数
thread_pool:线程池
num:想要添加的线程数目
返回值:
成功返回添加线程后的当前线程数目
失败返回0
int add_thread(thread_pool_t *thread_pool,int num)
{
//添加线程后的总线程数
unsigned total_treads = 0;
//如果num不合法或者已经达到最大线程数,直接返回
if(num<=0||thread_pool->current_active_threads>=thread_pool->max_active_threads)
return 0;
if(thread_pool->current_active_threads+num>thread_pool->max_active_threads){
total_treads = thread_pool->max_active_threads;
}
else{
total_treads = thread_pool->current_active_threads+num;
}
//创建线程
int i = 0,inc_threads = 0;
for(i=thread_pool->current_active_threads;i<total_treads;i++){
pthread_create(&thread_pool->id[i],NULL,start_routine,(void *)thread_pool);
//增加线程数+1
inc_threads++;
printf("线程%lu创建成功!\n",thread_pool->id[i]);
}
thread_pool->current_active_threads += inc_threads;
//返回添加的线程数
return inc_threads;
}
- 删除线程
参数:
thread_pool:线程池
num:想要删除的线程数目
返回值:
成功返回删除线程后当前的线程数目
失败返回0
int del_thread(thread_pool_t *thread_pool,int num)
{
//删除线程后的总线程数
unsigned total_treads = 0;
//如果num不合法或者已经只有一个线程,直接返回
if(num<=0||thread_pool->current_active_threads==1)
return 0;
//至少保留一个线程
if(thread_pool->current_active_threads-num<1){
total_treads = 1;
}
else{
total_treads = thread_pool->current_active_threads-num;
}
//删除数组最后指定个数的线程
int i = 0;
for(i=thread_pool->current_active_threads-1;i>total_treads-1;i--){
pthread_cancel(thread_pool->id[i]);
printf("线程%lu被取消!\n",thread_pool->id[i]);
}
//更新当前活动线程数
return thread_pool->current_active_threads = total_treads;
}
- 销毁线程池
参数:
thread_pool:线程池
int destroy_thread_pool(thread_pool_t *thread_pool)
{
//设置结束标志
thread_pool->shutdown = 1;
//唤醒所有睡眠的线程
pthread_cond_broadcast(&thread_pool->cond);
//等待所有线程就结束,回收结束线程的资源
int i;
for(i=0;i<thread_pool->current_active_threads;i++){
pthread_join(thread_pool->id[i],NULL);
printf("%lu线程结束!\n",thread_pool->id[i]);
}
//销毁链表
free(thread_pool->task_list);
thread_pool->task_list = NULL;
return 0;
}