线程池模块分析
1.main();
创建线程池。
向线程池中添加任务。借助回调处理任务。
销毁线程池。
2.pthreadpool_create();
创建线程池结构体指针。
初始化线程池结构体(N个成员变量)
创建n个任务线程
创建1个管理者线程
失败时销毁开辟的所有空间。(释放)
3.threadpool_thread();
进入子线程回调函数
接收参数 void *arg—>pool结构体
为整个结构体加锁
判断条件变量 – > wait
4.adjust_thread();
循环10s执行一次
进入管理者线程回调函数
接收参数pool结构体
为整个结构体加锁
获取线程池要用到的变量。
task_num,live_num,busy_num
根据既定算法,使用上述三变量,判断是否应该创建,销毁线程池中指定步长的线程
5.threadpool_add();
功能
模拟产生任务
设置回调函数处理任务
内部实现
加锁
初始化任务队列结构体成员。 回调函数function,arg
采用环形队列机制,实现添加任务。
唤醒阻塞在条件变量上的线程
解锁
6.从3.的wait之后继续执行,处理任务
加锁
获取任务处理回调函数,及参数
采用环形队列机制,实现处理任务。借助头指针实现
唤醒阻塞在条件变量上的server
解锁
加锁
改忙线程++
解锁
执行处理任务的线程、
加锁
改忙线程–
解锁
7.创建销毁线程
管理者线程根据既定算法,使用上述三变量,判断是否应该创建,销毁线程池中指定步长的线程
满足创建
pthread_create(); 回调任务函数 live_num++
满足销毁
wait_exit_thr_num = 10
signal给阻塞在条件变量上的线程发送家条件满足信号
跳转至—170 wait阻塞线程会被假信号唤醒。判断:wait_exit_thr_num > 0 pthread_exit();
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "threadpool.h"
#define DEFAULT_TIME 10
#define MIN_WAIT_TASK_NUM 10
#define DEFAULT_THREAD_VARY 10
#define true 1
#define false 0
typedef struct{
void *(*function)(void *);//任务的回调函数
void *arg;//函数的参数
}thread_pool_task_t;//子线程任务结构体
struct threadpool_t{
pthread_mutex_t lock;//此结构体为全局变量,所以此锁用于锁住本结构体
pthread_mutex_t thread_counter;//记录忙状态的锁 -- bust_thr_num
pthread_cond_t queue_not_full;//给服务器用的条件变量,任务队列不为满,通知客户端
pthread_cond_t queue_not_empty;//给线程池用的条件变量,任务队列不为空,通知线程
pthread_t *threads;//存放线程池中每个线程的tid
pthread_t adjust_tid;//存放管理线程
threadpool_task_t *task_queue;//任务队列(结构体数组)
int min_thr_num;//线程池最小线程数
int max_thr_num;//线程池最大线程数
int live_thr_num;//当前存活的线程个数
int busy_thr_num;//忙状态线程个数
int wait_exit_thr_num;//等待销毁的线程个数
int queue_front;//task_queue队头
int queue_rear;//队尾
int queue_size;//队列中的实际任务数量
int queue_max_size;//可容纳的任务数量的上限
int shutdown;//线程池使用状态
};
void *threadpool_thread(void *threadpool);
void *adjust_thread(void *threadpool);
int is_thread_alive(pthread_t tid);
int threadpool_free(threadpool_t *pool);
threadpool_t *threadpool_create(int min_thr_num,int max_thr_num,int queue_max_size)
{
int i;
threadpool_t *pool = NULL;
do{
if((pool = (threadpool_t *)malloc(sizeof(threadpool_t))) == NULL){
PRINTF("MALLOC THREADPOLL FAIL");
break;
}//线程池分配空间失败
pool->min_thr_num = min_thr_num;
pool->max_thr_num = max_thr_num;
pool->busy_thr_num = 0;
pool->live_thr_num = min_thr_num;
pool->wait_exit_thr_num = 0;
pool->queue_size = 0;
pool->queue_max_size = queue_max_size;
pool->queue->front = 0;
pool->queue->rear = 0;
pool->shutdown = false;//false表示为不关闭线程池
pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);
if(pool->threads == NULL){
printf("threads malloc fail");
break;
}
memset(pool->threads,0,sizeof(pthread_t)*max_thr_num);//初始化保存tid的数组
pool->task_queue = (threadpool_task_t *)malloc(sizeof(threadpool_task_t *)*queue_max_size);
if(pool->task_queue == NULL){
printf("task_queue malloc fail");
break;
}//初始化任务队列
if(pthread_mutex_init(&(pool->lock),NULL) != 0
|| pthread_mutex_init(&(pool->thread_counter),NULL) != 0
|| pthread_cond_init(&(pool->queue_not_empty),NULL) != 0
|| pthread_cond_init(&(pool->queue_not_full),NULL) != 0)
{
printf("init the lock or cond fail");
break;
}//初始化锁
for(i = 0; i < min_thr_num; i++){
pthread_create(&(pool->thread[i]),NULL,threadpoll_thread,(void *)pool);
printf("start thread 0x%x...\n",(unsigned int)pool->threads[i]);
}//创建线程
pthread_create(&(pool->adjust_tid),NULL,adjust_thread,(void *)pool);
return pool;
}while(0);
threadpool_free(pool);//前面的代码调用失败,释放存储空间
return NULL;
}
void *threadpool_thread(void *threadpool)
{
threadpool_t *pool = (threadpool_t *) threadpool;//接受线程池结构体
threadpool_task_t task;//定义一个任务结构体
while(true){
pthread_mutex_lock(&(pool->lock));
while((pool->queue_size == 0) && (!pool->shutdown)) {
printf("thread 0x%x is waiting\n",(unsigned int)pthread_self());
pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock));
if(pool->wait_exit_thr_num > 0){
pool->wait_exit_thr_num--;
if(pool->live_thr_num > pool->min_thr_num){
printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
pool->live_thr_num--;
pthread_mutex_unlock(&(pool->lock));
pthread_exit(NULL);
}
}
}//queue_size == 0,说明没有任务,调用wait阻塞在该变量上
if(pool->shutdown){
pthread_mutex_unlock(&(pool->lock));
printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
pthread_detach(pthread_self());//设置线程分离
pthread_exit(NULL);//终止线程
}
/*从任务队列里获取任务*/
task.function = pool->task->task_queue[pool->queue_front].function;
task.arg = pool->task_queue[pool->queue_front].arg;
pool->queue_front = (pool->queue_front + 1) % pool -> queue_max_size;
pool->queue_size--;
pthread_cond_broadcast(&(pool->queue_not_full));//通知有新任务可以添加
pthread_mutex_unlock(&(pool->lock));//任务取出后,马上释放线程池
/*执行任务*/
printf("thread 0x%x start working\n",(unsigned int)pthread_self());
pthread_mutex_lock(&(pool->thread_counter));
pool->busy_thr_num++;
pthread_mutex_unlock(&(pool->thread_counter));//忙状态
(*(task.function))(task.arg); //执行任务的回调函数
printf("thread 0x%x end working\n",(unsigned int)pthread_self());
pthread_mutex_lock(&(pool->thread_counter));
pool->busy_thr_num--;
pthread_mutex_unlock(&(pool->thread_counter));
}
pthread_exit(NULL);
}
void *adjust_thread(void *threadpool)
{
int i;
threadpool_t *pool = (threadpool_t *)threadpool;
while(!pool->shutdown){
sleep(DEFAULT_TIME); // 定时对线程进行管理
pthread_mutex_lock(&(pool->lock));
int queue_size = pool->queue_size;
int live_thr_num = poll->live_thr_num;
pthread_mutex_unlock(&(pool->lock));
pthread_mutex_lock(&(pool->thread_counter));
int busy_thr_num = poll->busy_thr_num;
pthread_mutex_unlock(&(pool->thread_counter));
if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num){
pthread_mutex_lock(&(pool->lock));
int add = 0;
for(i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY
&& pool->live_thr_num < pool->max_thr_num; i++){
if(pool->threads[i] == 0 || is_thread_alive(pool->threads[i])){
pthread_create(&(pool->thread[i]),NULL,threadpool_thread,(void *)pool);
add++;
pool->live_thr_num++;
}
}
pthread_mutex_unlock(&(pool->lock));
}//增加线程数
if((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num){
pthread_mutex_lock(&(pool->lock));
pool->wait_exit_thr_num = DEFAULT_THREAD_VARY; //要销毁的线程数
pthread_mutex_unlock(&(pool->lock));
for(i = 0; i < DEFAULT_THREAD_VARY; i++){
pthread_cond_signal(&(pool->queue_not_empty));
}//通知空闲状态的线程,让他们自行终止
}
}
return NULL;
}
int threadpool_add(threadpool_t *pool,void *(*function)(void *)arg,void *arg)
{
pthread_mutex_lock(&(pool->lock));
while((pool->queue_size == pool->queue_max_size) && !(pool->shutdown)) {
pthread_cond_wait(&(pool->queue_not_full),&(pool->lock));
}//队列已满,调wait阻塞
if(pool->shutdown) {
pthread_cond_broadcast(&(pool->queue_not_empty));
pthread_mutex_unlock(&(pool->lock));
return 0;
}//关闭线程
if(pool->task_queue[pool->queue_rear].arg != NULL) {
pool->task_queue[pool->queue_rear].arg = NULL;
}//清空工作线程调用的回调函数的参数arg
pool->task_queue[pool->queue_rear].function = function;
pool->task_queue[pool->queue_rear].arg = arg;
pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;//模拟环形
pool->queue_size++;
pthread_cond_signal(&(pool->queue_not_empty));
pthread_mutex_unlock(&(pool->lock));
return 0;
}
int threadpool_destroy(threadpool_t *pool)
{
int i;
if(pool == NULL){
return -1;
}
pool->shutdown = true;
pthread_join(pool->adjust_tid,NULL);//销毁管理线程
for(i = 0; i < pool->live_thr_num; i++){
pthread_cond_broadcast(&(pool->queue_not_empty));
}
for(i = 0; i < pool->live_thr_num; i++){
pthread_join(pool->threads[i],NULL);
}
threadpool_free(pool);
return 0;
}
int threadpool_free(threadpool_t *pool)
{
if(pool == NULL)
return -1;
if(pool->task_queue)
free(task_queue);
if(pool->threads){
free(pool->threads);
pthread_mutex_lock(&(pool->lock));
pthread_mutex_destroy(&(pool->lock));
pthread_mutex_lock(&(pool->thread_counter));
pthread_mutex_destroy(&(pool->thread_counter));
pthread_cond_destroy(&(pool->queue_not_empty));
pthread_cond_destroy(&(pool->queue_not_full));
}
free(pool);
pool = NULL;
return 0;
}
void *process(void *arg)
{
printf("thread 0x%x working on task %d\n",(unsigned int)pthread_self(),(int)arg);
sleep(1);
printf("task %d is end\n",(int)arg);
return NULL;
}
int main()
{
threadpool_t *thp = threadpool_create(3,100,100);//创建线程池
printf("pool inited");
int num[20],i;
for (i = 0; i < 20; i++){
num[i] = i;
printf("add task %d\n",i);
threadpool_add(thp,process,(void*)&num[i]);//向线程池添加任务
}
sleep(10);//等待子线程完成任务
threadpool_destroy(thp);//销毁线程池
return 0;
}