概述
什么是线程池:
线程池就是线程的集合,里面存放了一系列的线程。
线程池使用于需要大量创建和销毁线程的情况,使用线程池比单个线程的创建和销毁速度要快。
线程池的结构:
任务队列:任务队列是任务的生产者,存储需要处理的任务,工作线程会处理这些任务。
线程池:线程池中存放着工作线程,它是任务队列任务的消费者,等待新任务的信号。
固定大小线程池的实现:
1、创建线程池的基本结构:任务队列结构体、线程池结构体
2、线程池初始化:创建线程池结构、互斥锁和条件变量初始化、创建n个工作线程
3、线程池添加任务:判断是否有空闲线程、给任务队列添加节点、给工作线程发送信号
4、实现工作线程:等待任务信号、从任务队列中取出任务、执行任务
5、线程池销毁:删除任务队列、互斥锁、条件变量、线程池
线程池的实现
1、结构体实现
1.1 任务队列结构体
任务被抽象为一个函数,队列需要一个指针指向下一个节点。
具体结构体声明如下:
//任务队列
typedef struct Task{
void* (*func)(void* arg);//任务处理函数
void* arg; //任务处理函数的参数
struct Task* pNext; //链表指针
}Task;
1.2 线程池结构体
任务是一个临界资源,同一时刻只允许有一个线程处理该任务,所以需要一个互斥量。
任务和工作线程为生产者和消费者的关系,所以需要一个条件变量。
线程池中有多个工作线程,所以需要一个线程TID数组
线程与任务之间需要交互,所以需要当前正在工作线程的个数、当前需要处理的任务
具体结构体声明如下:
//线程池
#define POOL_NUM 5
typedef struct ThreadPool{
pthread_mutex_t taskLock; //互斥锁
pthread_cond_t newTask; //条件变量
pthread_t tid[POOL_NUM]; //线程TID
Task* queue_head; //任务队列头部
Task* queue_tail; //任务队列尾部
int busyWork; //当前正在工作的线程数量
}ThreadPool;
ThreadPool* pPool;
2、创建和销毁线程池
2.1 初始化线程池
线程池初始化就是申请线程池空间,并初始化互斥量、条件变量、任务队列、工作线程数量、创建工作线程。
具体代码实现如下:
/*
* pool_init:线程池初始化
* @ret -1--err 0--success
*/
int pool_init(void){
//1.申请空间
if((pPool = malloc(sizeof(ThreadPool))) == NULL){
printf("malloc err\n");
return -1;
}
//2.初始化
pthread_mutex_init(&