一、线程池的作用
1、降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗;
2、提高响应速度:当任务到达时,可以直接抛给线程池处理,不用等待线程创建;
3、异步解耦的作用。
例:高性能服务器在处理高并发的链接时,每建立一个连接,都要将这个连接的信息进行存储,
这样就会大大降低服务器处理客户端连接的能力,因此引入一个线程池,主线程只处理连接工作,
将存储(写盘)的工作全部抛给线程池进行处理,这样将大大提高服务器的qps。
二、工作原理
1、线程池的核心API:
1、创建/初始化:create/init
2、给线程池抛任务:push_task
3、销毁线程池:Destroy/deinit
2、用生活实例类比分析线程池的组成:
线程池由两大模块组成:执行队列(线程)、等待队列(任务)。
线程池就相当于是管理任务执行队列和任务等待队列的一个管理器。
以银行的营业大厅为例,它的工作原理和线程池的工作原理是类似的;营业厅就可以看作是我们整个线程池的结构,柜员相当于线程,
前来办业务的客户就相当于是任务,叫号公示牌是为了管理柜员和客户之间有秩序的进行业务处理。
模拟一人办理业务,进入营业厅后首先抽号在等待区等待,然后根据叫号提示牌,到指定柜员处办理业务,其中很关键的点就是公示牌的作用,
不允许两个客户同时在同一个柜员处办理业务,也不允许一个客户同时在两个柜员处办理业务,因此保证了整个营业厅内工作有秩序的进行。
这个过程就和线程池处理任务是一个道理,有任务来临后,先将任务加入到等待队列中,通过任务管理器,把任务派给相应的线程执行,
这个任务管理器的作用就是统筹任务和线程之间的平稳运行,这也就是线程池
说到底线程池其实就是一个生产者-消费者模型。
3、工作流程:
任务来临后,首先加入到等待队列,
然后根据线程池任务管理器的调度,将任务抛给执行队列处理任务
如下图所示:
三、线程池的主要结构体设计
1、工作队列结构体
typedef struct NWORKER
{
pthread_t id; //线程id
int terminate; //终止任务标志,判断此线程是否正在工作
struct NTHREADPOOL *pool; //线程池
struct NWORKER *prev; //前域指针
struct NWORKER *next; //后域指针
} nworker;
2、任务队列结构体
typedef struct NJOB
{
void (*job_func)(struct NJOB *job); //任务函数(有不同种任务)
void *user_data; //任务函数所对应的参数
struct NJOB *prev; //前域指针
struct NJOB *next; //后域指针
} njob;
3、线程池结构体(任务管理器)
typedef struct NTHREADPOOL
{
struct NWORKER *workers; //任务执行队列
struct NJOB *wait_jobs; //任务等待队列
pthread_cond_t cond; //条件变量
pthread_mutex_t mtx; //互斥锁
} nthreadpool;
四、线程池的主要代码实现
1、线程池的创建:
2、线程池的销毁:
3、线程池的push任务:
4、线程池的线程任务: