Linux(服务器编程3.1):---高并发线程池的设计(c实现pthread_pool)

一、设计线程池的优点、作用

线程池作用就是限制系统中执行线程的数量。根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

为什么要用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

二、使用场景

暂时了解用到两点:
1,高并发下的IO异步操作;
2,日志的存储(落盘);

三、线程池的设计

Linux(服务器编程3.1):---高并发线程池的设计(c实现pthread_pool)_第1张图片
工作流程说明:
初始化创建n个线程,等待任务队列添加task,每添加一个task,则唤醒一个线程,并执行相应任务的回调函数。并根据空闲线程的数量动态增加和减少线程的数量,线程数量最少10个,一般设计线程池最佳工作方式为:当free_threads < sum_threads * 0.4(即有60%以上的线程busy),会增加threads数量;当free_threads > sum_threads * 0.4 * 0.8(即有20%以下的线程是busy)。

  • 本线程池包括3个内容:
    • tasks节点
    • threads节点
    • 线程池管理组件
**task节点**
		功能:就是一个任务,其有一个回调函数,用于执行任务
		特点:管当有新任务加入线程池之后,这个任务会被线程池分配给线程去处理
//tast struct ;
typedef struct NJOB{
	//任务回调
	void (*func)(void *arg);
	void *user_data;  //用户数据信息
	
	struct NJOB *next;
	struct NJOB *prev;
}nJob;
**线程节点**
		功能:单个线程的表示结构体,可以用来处理任务
		特点:线程各自运行在自己的pthread_create()回调函数中,一直不间断的执行任务
//thread struct
typedef struct NWORKER{
	pthread_t thread_id;     //线程id
	int terminate;   //退出标志
	int busy;       //1--表示线程正在工作
	struct NMANGER *pool;  //可以拿到管理组件
	
	struct NWORKER *next;
	struct NWORKER *prev;	
}nworker;
**线程池**
		功能:线程池对象,保存着任务和所有的线程(包括线程数量检测线程,用于动态管理线程数量)
//线程池管理组件,添加动态增加和删除线程功能
typedef struct NMANGER{
	nworker *workers;
	nJob *jobs;
	
	int sum_threads;   //线程总数
	int free_threads; //空闲线程数
	int terminate;     //监控moniter线程退出标志
	pthread_t monitorTid;   //监控moniter线程id
	//void (*monitorCallback)(void *arg);   //用于监控sum_threads和free_threads
	//互斥锁,条件变量
	pthread_mutex_t jobs_mtx;
	pthread_cond_t jobs_cond;
}nManager;	

四、编程实现

由于task和thread节点都是双向链表,所以节点的添加和删除可以采用宏实现(无需写两套代码),实现数据与业务的分离。也可以使用c++模板;
//node head insert
//使用宏,nWorkers与nJobs可通用一个LL_ADD,同时操作一个性质
#define LL_ADD(item,  list) do{   		  \
	item->next = list;        			   \
	item->prev = NULL;        			    \
	list = item;                              \
}while(0)

//使用宏,nWorkers与nJobs可通用一个LL_REMOVE
/*if(item == list) list = item->next;    如果是头节点,则后移动*/
#define LL_REMOVE(item, list) do{                          \
	if(item->prev != NULL) item->prev->next = item->next;  \
	if(item->next != NULL) item->next->prev = item->prev;   \
	if(item == list) list = item->next;                      \
	item->prev = item->next = NULL;                          \
}while(0)
C实现线程池的API:
//线程池初始化
int thread_pool_create(nThreadPool *pool, int numWorkers);
//线程销毁
int nThreadPoolDestroy(nThreadPool *pool);
//task 添加到队列中
int nThreadPoolPushJobs(nThreadPool *pool, nJob *jobs);
//线程业务回调函数;
void *nWorkerCallback(void *arg)//线程监控函数----动态检测
void *monitorThread(void *arg)

Github开源地址:https://github.com/Fang-create/pthread_pool

参考:https://blog.csdn.net/qq_41453285/article/details/106622568

你可能感兴趣的:(后端服务器开发)