线程池
线程池(thread pool)
线程池时一种多线程处理形式,处理过程 将任务添加到任务队列上,
然后在创建线程后自动启动这些任务
注意:
1. 任务队列刚开始是没有任务,是一个具有头结点的空链队列
2. 使用互斥锁来保护这个任务链表
3. 是使用条件变量来代表任务队列上任务个数的变化
4. 通过一个公共开关--shutdown 来控制线程的退出,进而销毁整个线程池
5. 活动线程执行完任务函数之后不会退出,继续向生产者索要任务,继续执行,没有任务
进行休眠
线程池的接口函数:
1.初始化线程池
bool init_pool(thread_pool*pool,int thread_num);
2.添加任务
bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg);
3.销毁线程池
bool destroy_pool(thread_pool*pool);//看具体空间段
4. 往线程池中添加活动线程
....
NAME
pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancel‐
lation clean-up handlers
SYNOPSIS
#include <pthread.h>
这两个函数专门用于防止线程被取消后死锁的
//在线程死亡的时候做清理工作
void pthread_cleanup_push(void (*routine)(void *),
void *arg);//清理函数入栈
void pthread_cleanup_pop(int execute);//出栈
Compile and link with -pthread.
注意:
这是匹配使用
#ifndef __THREAD_POOL__
#define __THREAD_POOL__
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
struct task_node
{
void*(*do_task)(void*);
void*arg;
struct task_node*next;
};
struct Head//队列头节点
{
struct task_node* first;
struct task_node* last;
int num;
};
//声明线程池类型
typedef struct thread_pool
{
pthread_mutex_t mutex;//互斥锁
pthread_cond_t cond;//条件变量
bool shutdown;//开关 是否关闭
int task_max;//最大任务数
struct Head*h;//任务队列头节点指针
int threads_max;//线程最大数
int threads_num;//活动线程数
pthread_t *tid;//指针,指向线程ID数组空间
//。。。
}thread_pool;
extern bool init_pool(thread_pool*pool,int thread_num);
extern bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg);
extern bool destroy_pool(thread_pool*pool);
#endif
#include "thread_pool.h"
#define TASK_MAX 1024
#define THREADS_MAX 20
void handle(void*arg)
{
thread_pool* pool = (thread_pool*)arg;
pthread_mutex_unlock(&pool->mutex);
}
//线程函数
void*thread_running(void* arg)
{
thread_pool* pool = (thread_pool*)arg;
struct task_node*p = NULL;//执行要执行的任务节点
while(1)
{
//上锁之前注册一个清理函数,避免被取消死锁
pthread_cleanup_push(handle,pool);
//1.上锁访问任务队列
pthread_mutex_lock(&pool->mutex);
//2. 访问任务队列
// 无任务且线程池未关闭 wait
while(pool->h->num == 0 && !pool->shutdown)//被唤醒之后检测条件是否依然满足
{
pthread_cond_wait(&pool->cond, &pool->mutex);
//唤醒:
//1. 有任务
//2. 线程池要关闭的时候
}
// 无任务且线程池关闭 线程死亡
if(pool->h->num == 0 && pool->shutdown)
{
//先解锁在退出
pthread_mutex_unlock(&pool->mutex);
pthread_exit(NULL);
}
// 有任务开始在任务队列上拿去任务节点
p = pool->h->first;
pool->h->first = p->next;// pool->h->first = pool->h->first->next;
pool->h->num--;
//拿去任务之后解锁
pthread_mutex_unlock(&pool->mutex);
//出栈刚刚注册用不到的清理函数
pthread_cleanup_pop(0);
//3. 执行任务
//执行任务之前设置不可被取消
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
//执行任务
p->do_task(p->arg);// 使用函数指针调用任务函数
//执行任务之后设置可被取消
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
free(p);
p = NULL;
}
}
/*
init_pool:初始化一个线程池
@pool: 指向要初始的线程池
@thread_num:线程池中的活动线程数
返回值:
成功 返回true
失败 返回false
*/
bool init_pool(thread_pool*pool,int thread_num)
{
pthread_mutex_init(&pool->mutex, NULL);//初始互斥锁
pthread_cond_init(&pool->cond, NULL);//初始条件变量
pool->shutdown = false;//非 关闭状态
pool->task_max = TASK_MAX;
pool->h = malloc(sizeof(struct Head));//任务队列头节点指针
if(pool->h == NULL)
return false;
pool->h->first = pool->h->last = NULL;
pool->h->num = 0;//任务队列的节点数 0
pool->threads_max = THREADS_MAX;//线程最大数
if(thread_num > THREADS_MAX)
pool->threads_num = THREADS_MAX;//活动线程数
else
pool->threads_num = thread_num;
pool->tid = malloc(THREADS_MAX*sizeof(pthread_t));//指针,指向线程ID数组空间
if(pool->tid == NULL)
{
free(pool->h);
return false;
}
for(int i = 0; i < pool->threads_num; i++)
{
int re = pthread_create(&pool->tid[i], NULL, thread_running, pool);
if(re == -1)
{
perror("pthread_create :");
return false;
}
}
return true;
}
/*
add_task:往线程池中添加任务
@pool :执行要操作的线程池
@do_task:函数指针
执行要执行的任务函数
@arg: 任务函数 的参数
返回值:
成功 真
失败 假
*/
bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg)
{
if(pool == NULL)
return false;
//创建新节点
struct task_node*pnew = malloc(sizeof(*pnew));
if(pnew == NULL)
return false;
pnew->do_task = do_task;
pnew->arg = arg;
pnew->next = NULL;
//增加到任务队列上
pthread_mutex_lock(&pool->mutex);
//任务队列满队
if(pool->h->num == pool->task_max)
{
free(pnew);
pthread_mutex_unlock(&pool->mutex);
return false;
}
if(pool->h->num == 0)//空队列
{
pool->h->first = pool->h->last = pnew;
}
else
{
pool->h->last->next = pnew;
pool->h->last = pnew;
}
pool->h->num++;
pthread_mutex_unlock(&pool->mutex);
pthread_cond_signal(&pool->cond);
return true;
}
/*
*/
bool destroy_pool(thread_pool*pool)
{
pool->shutdown = true;//开关 是否关闭
//唤醒所有的睡眠线程
pthread_cond_broadcast(&pool->cond);
//等待所有活动线程死亡
for(int i = 0; i < pool->threads_num; i++)
{
pthread_join(pool->tid[i], NULL);
}
free(pool->h);
free(pool->tid);//指针,指向线程ID数组空间
pthread_mutex_destroy(&pool->mutex);//互斥锁
pthread_cond_destroy(&pool->cond);//条件变量
//free(pool);
return true;
}