线程池[高级]

#线程池配置文件filename:[thread_pool_config.conf] 其中‘#’为注释 不准以=开始
#线程池最小线程数
MIN_THREAD_NUM = 3

#线程池最大线程数
MAX_THREAD_NUM =50

#线程池默认线程数
DEF_THREAD_NUM = 25

#管理线程动态调节时间间隔(s)
MANAGE_ADJUST_INTERVAL = 5

#线程数与任务峰值比例
THREAD_WORKER_HIGH_RATIO = 3

#任务数与线程数低谷比例
THREAD_WORKER_LOW_RATIO = 1




说明:这里有3个参数比较关键:
    其中MANAGE_ADJUST_INTERVAL 表示管理线程的动态调节时间间隔,这里线程池的动态调优是通过后台线程统一管理,类似nginx中的master进程。
    THREAD_WORKER_HIGH_RATIO 指的是任务数目是线程数目的多少倍,主要指示任务峰值状态,也就是满负载状况下,需要增加线程(当然线程不能无限指增加,不然的话会增加CPU的负担,这里用MAX_THREAD_NUM 来限制最大线程数)
    THREAD_WORKER_LOW_RATIO 指的是任务数目是线程数目的多少倍,主要指示任务平静期,这时很多线程处于阻塞空闲状态,需要减少线程,以便均衡资源。

配置文件读取模块[readConf.c]不在赘述。

基于初级的线程池优化,这里最主要的问题是解决线程id的管理问题,以及线程取消的管理
这里采用链表来管理线程id,链表的特性便于新增和删除,这里就不在多说了,不懂的可以去看一下维斯的数据结构与算法分析了。
引进thread_revoke结构体来标记全局的取消线程信息,先分析一下线程什么时候需要取消:当任务很少,少到tasknum <threadnum* THREAD_WORKER_LOW_RATIO 时,也就是,任务的增加速度远远赶不上线程的处理速度时,会导致一部分线程处于饥饿状态(阻塞)。那么我们需要取消的就是处于饥饿状态的线程。对于poisx多线程编程中线程的取消,一般采用pthread_cancel()而且此函数是无阻塞返回的(即不等线程是否真的取消)而且,这里有一个很大很大的疑惑,在线程取消的时候,线程必须等到在取消执行点处取消,这里我们的取消执行点是pthread_cond_wait()这线程处理阻塞状态,互斥锁在线程插入阻塞等待队列时已经释放掉。但是,线程本身处于阻塞状态下(放弃了时间片)会执行取消动作吗?我试验了一下,没有……
这里维护一个取消队列,在线程取消时,置全局取消标志位为1,pthread_broadcast()唤醒所有线程,让在线程唤醒时会判断是否进入取消状态,如果是直接主动退出。当然这里有一个取消计数。
先等一等,这样会不会影响到正在工作的线程?答案是不会,因为在工作中的线程已经跳过了线程取消验证~


/**filename:thread_pool.h
  */
#ifndef _THREADPOOL_HEAD_
#define _THREADPOOL_HEAD_

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include "readConfig.h"

/**********************宏定义区********************/

/* 配置文件名  */
#define CONFIGFILENAME "thread_pool_config.conf"

/* 线程池最小线程数 */
#define MIN_THREAD_NUM "MIN_THREAD_NUM"

/* 线程池最大线程数 */
#define MAX_THREAD_NUM "MAX_THREAD_NUM"

/* 线程池默认线程数 */
#define DEF_THREAD_NUM "DEF_THREAD_NUM"

/* 管理线程动态调节时间间隔(s) */
#define MANAGE_ADJUST_INTERVAL "MANAGE_ADJUST_INTERVAL"

/* 线程数与工作峰值比例 */
#define THREAD_WORKER_HIGH_RATIO "THREAD_WORKER_HIGH_RATIO"

/* 任务与线程数低谷比例 */
#define THREAD_WORKER_LOW_RATIO "THREAD_WORKER_LOW_RATIO"





/************************结构体声明区*************************/

/*
 *线程池里所有运行和等待的任务都是 一个thread_worker
 *由于所有任务都在链表中,所以是一个链表结构
 */
typedef struct _worker{
	void *(*process)(void *arg);   	/* 工作的处理函数指针 */
	void *arg;					   	/* 处理函数的参数  */
	struct _worker *next;		  	/* 下一个工作  */
}thread_worker;

/*  线程队列节点结构  */
typedef struct _thread_queue_node{
	pthread_t 	thread_id;
	struct _thread_queue_node *next;
}thread_queue_node,*p_thread_queue_node;

/* 线程池结构  */
typedef struct {
	int			shutdown;			/* 是否销毁线程池  */
	pthread_mutex_t 	queue_lock;			/* 线程锁  */
	pthread_mutex_t 	remove_queue_lock;		/* 线程锁  */
	pthread_cond_t		queue_ready;			/* 通知等待队列有新任务条件变量  */
	thread_queue_node 	*thread_queue;			/* 线程池的线程队列 */
	thread_queue_node 	*thread_idle_queue;
	int 			idle_queue_num;	
	int 			max_thread_num; 		/* 线程池中允许开启的最大线程数  */
	int 			cur_queue_size;			/* 当前等待队列的任务数目  */
	thread_worker 		*queue_head;			/* 线程池所有等待任务  */
}thread_pool;

/* 线程取消  */
typedef struct {
	int 			is_revoke; 		/*是否需要撤销线程*/
	int 			revoke_count;		/* 已经撤销的线程数  */
	int 			revoke_num;		/* 需要撤销的总数  */
	pthread_mutex_t 	revoke_mutex; 		/* 撤销线程加锁  */
	thread_queue_node 	*thread_revoke_queue;	/* 线程撤销队列 */
}thread_revoke;

/**************************功能函数声明区************************/

/** 向线程池中添加任务  **/
int pool_add_worker(void *(*process)(void *arg), void *arg);

/** 线程池中的线程  **/
void *thread_routine(void *arg);

/** 初始化线程池  **/
void pool_init(int max_thread_num);

/**  销毁线程池  **/
int pool_destroy();

/** 向线程池中追加线程 **/
void pool_add_thread(int thread_num);

/** 向线程队列中追加线程 **/
int thread_queue_add_node(p_thread_queue_node *thread_queue, pthread_t thread_id,int * count);

/**  撤销线程  **/
void pool_revoke_thread(int thread_num);

/**  从线程队列删除线程  **/
int thread_queue_remove_node(p_thread_queue_node *thread_queue, pthread_t thread_id,int *count);

/** 获取配置文件中某一项的值  **/
int get_config_value(char * item);

/*****************全局变量声明区******************/
/* 线程池  */
extern thread_pool 		*g_pool;

/* 线程取消  */
extern thread_revoke 	*g_thread_revoke;

/* 线程池最大线程数  */
extern int 				g_max_thread_num;

/* 线程池最小线程数  */
extern int 				g_min_thread_num;

/* 默认线程池线程数  */
extern int 				g_def_thread_num;	

/* 管理线程调整时间间隔  */
extern int 				g_manage_adjust_interval;

/* 线程任务峰值比率:衡量负载 */
extern int 				g_thread_worker_high_ratio;	

/* 线程任务低谷比率:衡量负载 */
extern int 				g_thread_worker_low_ratio;	

#endif


/**	filename:thread_pool.c
 */
#include "threadpool.h"

/**************** 全局变量定义区 ***************/
 
thread_pool  	*g_pool = NULL;
thread_revoke 	*g_thread_revoke = NULL;
int				g_def_thread_num = 0;
int				g_manage_adjust_interval = 0;
int 			g_max_thread_num = 0;
int 			g_min_thread_num = 0;
int 			g_thread_worker_high_ratio = 0;
int 			g_thread_worker_low_ratio = 0;


/**	函数名:	get_config_value  int 的项值
   *	功能描述:	获取配置文件中某一项的值
   *	参数列表:  item:为配置文件中的项名
   *	返回值:	出错返回-1 成功返回项的值	 
   */
 int get_config_value(char *item)
{
	char value[50];
	if(GetParamValue(CONFIGFILENAME,item,value) == NULL)
	{
		return -1;
	}

	return atoi(value);
}


 /**	函数名:	get_config_value  int 的项值
   *	功能描述:	初始化配置文件项变量的值
   *	参数列表:  无
   *    返回值:	无	 
   */
void conf_init()
{
	g_max_thread_num = get_config_value(MAX_THREAD_NUM);
	g_min_thread_num = get_config_value(MIN_THREAD_NUM);
	g_def_thread_num = get_config_value(DEF_THREAD_NUM);
	g_manage_adjust_interval = get_config_value(MANAGE_ADJUST_INTERVAL);
	g_thread_worker_high_ratio = get_config_value(THREAD_WORKER_HIGH_RATIO);
	g_thread_worker_low_ratio = get_config_value(THREAD_WORKER_LOW_RATIO);

}
/**	函数名:	pool_init 
  * 功能描述:	初始化线程池
  *	参数列表:	max_thread_num :输入要建的线程池的线程最大数目
  *	返回值:	无
  */
void pool_init(int max_thread_num)
{
	int i;
	conf_init();
	if(max_thread_num < g_min_thread_num)
	{
		max_thread_num = g_min_thread_num;
	}
	else if(max_thread_num > g_max_thread_num)
	{
		max_thread_num = g_max_thread_num;
	}
	pthread_attr_t attr;
	int err;
	err= pthread_attr_init(&attr);
	if(err != 0)
	{
		perror("pthread_attr_init");
		exit(1);
	}
	err = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

	if(err != 0)
	{
		perror("pthread_attr_setdetachstate");
		exit(1);
	}

	g_pool = (thread_pool *)malloc(sizeof(thread_pool));
	
	pthread_mutex_init(&(g_pool->queue_lock),NULL);
	pthread_mutex_init(&(g_pool->remove_queue_lock),NULL);
	pthread_cond_init(&(g_pool->queue_ready),NULL);

	g_pool->queue_head = NULL;
	g_pool->max_thread_num = max_thread_num;
	g_pool->thread_queue =NULL;
	g_pool->thread_idle_queue = NULL;
	g_pool->idle_queue_num = 0;
	g_pool->cur_queue_size = 0;
	g_pool->shutdown = 0;

	int temp;
	for(i = 0; i < max_thread_num; i++)
	{
		pthread_t thread_id;
		pthread_create(&thread_id,&attr,thread_routine,NULL);
		thread_queue_add_node(&(g_pool->thread_queue),thread_id,&temp);
		printf("temp&&&&&&&&&&&&&%d\n",temp);

	}
	
	pthread_attr_destroy(&attr);

}

void thread_revoke_init()
{
	g_thread_revoke = (thread_revoke *)malloc(sizeof(thread_revoke));
	
	pthread_mutex_init(&(g_thread_revoke->revoke_mutex),NULL);
	g_thread_revoke->thread_revoke_queue = NULL;
	g_thread_revoke->revoke_count = 0;
	g_thread_revoke->is_revoke = 0;
	g_thread_revoke->revoke_num = 0;
}
/**	函数名:	thread_queue_add_node

  * 功能描述:	向线程池中新增线程
  *	参数列表:	thread_queue:要增加的线程的线程队列 thread_id:线程的id
  *	返回值:	成功返回0 失败返回1
  */
int thread_queue_add_node(p_thread_queue_node *thread_queue,pthread_t thread_id,int *count)
{
	pthread_mutex_lock(&(g_pool->remove_queue_lock));
	printf("++++count:%d++++++add thread id :%u++++\n",*count,thread_id);
	thread_queue_node *p = *thread_queue;
	thread_queue_node *new_node = (thread_queue_node *)malloc(sizeof(thread_queue_node));
	if(NULL == new_node)
	{
		printf("malloc for new thread queue node failed!\n");
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 1;
	}
	
	new_node->thread_id = thread_id;
	new_node->next = NULL;
	
	/*如果队列为空*/
	if(NULL == *(thread_queue))
	{
		*(thread_queue) = new_node;
		(*count)++;		
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 0;
	}
	
	/*每次都将新节点插入到队列头部*/
	new_node->next = p;
	*(thread_queue) = new_node;
	(*count)++;		
	pthread_mutex_unlock(&(g_pool->remove_queue_lock));
	return 0;
}
int thread_queue_remove_node(p_thread_queue_node *thread_queue,pthread_t thread_id,int *count)
{

	pthread_mutex_lock(&(g_pool->remove_queue_lock));
	printf("---count:%d------remove threadid : %u----\n",*count,thread_id);
	p_thread_queue_node current_node,pre_node;
	if(NULL == *(thread_queue))
	{
		printf("revoke a thread node from queue failed!\n");
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 1;
	}

	current_node = *(thread_queue);
	pre_node = *(thread_queue);
	int i = 1;
	while(i < g_pool->max_thread_num && current_node != NULL)
	{
		printf("i = %d, max_thread_num = %d \n",i,g_pool->max_thread_num);
		i++;
		if(thread_id == current_node->thread_id)
		{
			break;
		}
		pre_node = current_node;
		current_node = current_node->next;
	
	}
	
	if(NULL == current_node)
	{
		printf("revoke a thread node from queue failed!\n");
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 1;
	}

	/*找到该线程的位置,删除对应的线程节点 如果要删除的节点就是头节点 */
	if(current_node->thread_id == (*(thread_queue))->thread_id)
	{
		*(thread_queue) = (*(thread_queue))->next;
		free(current_node);
		(*count)--;
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 0;
	}

	/*找到该线程的位置,删除对应的线程节点 如果要删除的节点就是尾节点 */
	if(current_node->next == NULL)
	{
		pre_node->next =NULL;
		free(current_node);
		(*count)--;
		pthread_mutex_unlock(&(g_pool->remove_queue_lock));
		return 0;
	}
	pre_node = current_node->next;
	free(current_node);
	(*count)--;
	printf("0 max_thread_num = %d\n",g_pool->max_thread_num);
	pthread_mutex_unlock(&(g_pool->remove_queue_lock));
	return 0;
}


/**	函数名:	pool_add_worker 
  * 功能描述:	向线程池中加任务
  *	参数列表:	process :函数指针,指向处理函数用作真正的工作处理
  *				arg:工作队列中的参数
  *	返回值:	成功返回0,失败返回-1
  */
int pool_add_worker(void*(*process)(void *arg),void *arg)
{
	thread_worker *new_work = (thread_worker *)malloc(sizeof(thread_worker));
	
	if(new_work == NULL)
	{
		return -1;
	}
	
	new_work->process = process;
	new_work->arg = arg;
	new_work->next = NULL;

	pthread_mutex_lock(&(g_pool->queue_lock));

	/*将任务加入等待队列中*/
	thread_worker *member = g_pool->queue_head;
	if(member != NULL)
	{
		while(member->next != NULL)
		{
			member = member->next;
		}

		member->next = new_work;
	}
	else
	{
		g_pool->queue_head = new_work;
	}

	assert(g_pool->queue_head != NULL);

	g_pool->cur_queue_size++;
	pthread_mutex_unlock(&(g_pool->queue_lock));
	/*等待队列中有新任务了,唤醒一个等待线程处理任务;注意,如果所有的线程都在忙碌,这句话没有任何作用*/
	pthread_cond_signal(&(g_pool->queue_ready));

	return 0;
}

/**	函数名:	pool_add_thread 

  * 功能描述:	向线程池中新增线程
  *	参数列表:	thread_num:要增加的线程数目
  *	返回值:	无
  */
void pool_add_thread(int thread_num)
{
	int i;
	pthread_attr_t attr;
	int err = pthread_attr_init(&attr);
	if(err != 0)
	{
		perror("pthread_attr_init");
		exit(1);
	}
	err = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

	if(err != 0)
	{
		perror("pthread_attr_setdetachstate");
		exit(1);
	}
	
	for(i = 0; i < thread_num; i++)
	{
		pthread_t thread_id;
		pthread_create(&thread_id,&attr,thread_routine,NULL);
		thread_queue_add_node(&(g_pool->thread_queue),thread_id,&(g_pool->max_thread_num));
	}

	pthread_attr_destroy(&attr);
}

/**	函数名:	pool_revoke_thread

  * 功能描述:	从线程池线程中撤销线程
  *	参数列表:	thread_num:要撤销的线程数目
  *	返回值:	无
  */
void pool_revoke_thread(int thread_num)
{
	if(thread_num == 0)
	{
		return;
	}

	g_thread_revoke->revoke_num =thread_num;
	g_thread_revoke->is_revoke = 1;
	printf("----max_thread_num %d---------revoke %d thread-----\n",g_pool->max_thread_num,thread_num);
	thread_queue_node * p = g_thread_revoke->thread_revoke_queue;

	pthread_cond_broadcast(&(g_pool->queue_ready));

}
void * thread_manage(void *arg)
{
	int optvalue;
	int thread_num;
	while(1)
	 {
	 
		 if(g_pool->cur_queue_size > g_thread_worker_high_ratio * g_pool->max_thread_num)
	 	{
			 optvalue = 1;
			 thread_num =(g_pool->cur_queue_size -g_thread_worker_high_ratio * g_pool->max_thread_num) / g_thread_worker_high_ratio;
		}
	 	else if (g_pool->cur_queue_size * g_thread_worker_low_ratio < g_pool->max_thread_num)
	 	{
			optvalue = 2;
			thread_num =(g_pool->max_thread_num -g_thread_worker_low_ratio * g_pool->cur_queue_size) / g_thread_worker_low_ratio;
	 	}
	 
		if(1 == optvalue)
	 	{
			
			if(g_pool->max_thread_num + thread_num > g_max_thread_num)
			{
				thread_num = g_max_thread_num - g_pool->max_thread_num;
			}
			pool_add_thread(thread_num);
			
	 	}
		else if( 2 == optvalue)
		{
			if(g_pool->max_thread_num - thread_num < g_min_thread_num)
			{
				thread_num = g_pool->max_thread_num - g_min_thread_num;
			}
		//	pthread_t revoke_tid;
		//	pthread_create(&revoke_tid,NULL,(void *)pool_revoke_thread,(void *)thread_num);
			pool_revoke_thread(thread_num);
	 	}

		printf("==========ManageThread=============\n");

		printf("cur_queue_size = %d  |  max_thread_num = %d\n",g_pool->cur_queue_size,g_pool->max_thread_num);
		conf_init();
		sleep(g_manage_adjust_interval);
 }



	
	
}


/**	函数名:	pool_destroy 
  * 功能描述:	销毁线程池
  *	参数列表:	无
  *	返回值:	成功返回0,失败返回-1
  */
int pool_destroy()
{
	if(g_pool->shutdown)
	{
		return -1;
	}
	
	g_pool->shutdown = 1;

	/* 唤醒所有等待线程,线程池要销毁  */
	pthread_cond_broadcast(&(g_pool->queue_ready));

	/* 阻塞等待线程退出,防止成为僵尸  */
	thread_queue_node * q = g_pool->thread_queue;
	thread_queue_node * p = q;
	
	g_pool->thread_queue = NULL;

	/* 销毁等待队列  */
	thread_worker *head = NULL;

	while(g_pool->queue_head != NULL)
	{
		head = g_pool->queue_head;
		g_pool->queue_head = g_pool->queue_head->next;
		free(head);
	}
	
	g_pool->queue_head = NULL;

	/* 条件变量和互斥量销毁  */
	pthread_mutex_destroy(&(g_pool->queue_lock));
	pthread_mutex_destroy(&(g_pool->remove_queue_lock));
	pthread_cond_destroy(&(g_pool->queue_ready));
	
	/* 销毁整个线程池  */
	free(g_pool);
	g_pool = NULL;

	return 0;
	
}

void cleanup(void *arg)
{
		thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num));
		pthread_mutex_unlock(&(g_pool->queue_lock));
		printf("thread ID %d will exit\n",pthread_self());
	
}

/**	函数名:	thread_routine 
  * 功能描述:	线程池中的线程
  *	参数列表:	arg 线程附带参数 一般为NULL;
  *	返回值:   
  */
void * thread_routine(void *arg)
{
	printf("starting thread ID:%u\n",pthread_self());
	while(1)
	{
		pthread_mutex_lock(&(g_pool->queue_lock));
		/* 如果等待队列为0 并且不销毁线程池,则处于阻塞状态
		 *pthread_cond_wait 是原子操作,等待前解锁,唤醒后加锁
		 */

		while(g_pool->cur_queue_size == 0 && !g_pool->shutdown )
		{
			printf("thread ID %u is waiting \n",pthread_self());
			pthread_cond_wait(&(g_pool->queue_ready),&(g_pool->queue_lock));
		}

		/* 如果线程池要销毁 */
		if(g_pool->shutdown)
		{
			thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num));
			pthread_mutex_unlock(&(g_pool->queue_lock));
			printf("thread ID %d will exit\n",pthread_self());
			pthread_exit(NULL);
		}

		if(g_thread_revoke->is_revoke != 0 && g_thread_revoke->revoke_count < g_thread_revoke->revoke_num)
		{
		/*	if(g_thread_revoke->revoke_count >= g_thread_revoke->revoke_num )
			{
				
			printf("-revoke-@@jie锁@@+++\n");	
				pthread_mutex_unlock(&(g_pool->queue_lock));
				continue;
			}*/
			thread_queue_remove_node(&(g_pool->thread_queue),pthread_self(),&(g_pool->max_thread_num));
		
			thread_queue_add_node(&(g_thread_revoke->thread_revoke_queue),pthread_self(),&(g_thread_revoke->revoke_count));
			g_thread_revoke->revoke_count++;
			pthread_mutex_unlock(&(g_pool->queue_lock));
			printf("revoke success thread ID %d will exit\n",pthread_self());
			pthread_exit(NULL);

		}

		printf("thread ID %u is starting to work\n",pthread_self());
		assert(g_pool->cur_queue_size != 0);
		assert(g_pool->queue_head != NULL);

		/* 等待队列长度减1,并且取出链表的头元素  */
		g_pool->cur_queue_size--;
		thread_worker * worker = g_pool->queue_head;
		g_pool->queue_head = worker->next;
		pthread_mutex_unlock(&(g_pool->queue_lock));
		printf("************执行任务\n");
		/* 调用回调函数,执行任务  */
		(*(worker->process))(worker->arg);
		free(worker);
		worker = NULL;
			
	}
	pthread_exit(NULL);
}

void *myprocess(void *arg)
{
	printf("thread ID is %u, working on task%d\n",pthread_self(),*(int *)arg);
	sleep(1);
	return NULL;
}

int main(int argc, char * argv[])
{
	pthread_t manage_tid;
	thread_revoke_init(); 	
	sleep(1);
	pool_init(g_def_thread_num);
	sleep(3);
	pthread_create(&manage_tid,NULL,thread_manage,NULL);

	int i;
	for(i = 0;  ; i++)
	{
		
		pool_add_worker(myprocess,&i);
		i++;
		pool_add_worker(myprocess,&i);
		i++;
		pool_add_worker(myprocess,&i);
		i++;
		pool_add_worker(myprocess,&i);
		sleep(1);
		if(i%8== 0)
		{
			sleep(10);
		}

		if(i%10 == 0)
		{
			sleep(20);
		}
	}

	sleep(5);
	printf("=======xiaohui========\n");
	pool_destroy();
    

	return 0;
}

转载请注明出处 http://blog.csdn.net/lingfengtengfei/article/details/9039135











评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值