一、设计线程池的优点、作用
线程池作用就是限制系统中执行线程的数量。根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。
为什么要用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
二、使用场景
暂时了解用到两点:
1,高并发下的IO异步操作;
2,日志的存储(落盘);
三、线程池的设计
工作流程说明:
初始化创建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