pthread_pool,POSIX的线程池实现

线程池,根据命令行参数,传递连接的端口号,线程个数,任务个数(即连接次数)
可以测试server的并发


#include<arpa/inet.h>
#include<string.h>
#include<sys/socket.h>
#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<assert.h>
//任务链表结点
typedef struct worker
{
	void* (*process)(void* arg);//任务处理函数
	void* arg;//函数参数
	struct worker* next;//指向下一个任务结点
}CThread_worker;

//线程池结构
typedef struct{
	pthread_mutex_t queue_lock;//互斥锁
	pthread_cond_t queue_ready;//条件变量
	CThread_worker* queue_head;//任务链表头指针
	int shutdown;//是否关闭线程池,1关
	pthread_t* threadid;//线程池描述符
	int max_thread_num;//允许活动的最大数目
	int cur_queue_size;//当前任务链表的数目
}CThread_pool;

int pool_add_worker(void* (*process)(void* arg),void* arg);
void* thread_routine(void* arg);

//全局变量,定义一个线程池指针
static CThread_pool* pool = NULL;

//线程池初始化
void pool_init(int max_thread_num){
	pool = (CThread_pool*)malloc(sizeof(CThread_pool));
	pthread_mutex_init(&pool->queue_lock,NULL);
	pthread_cond_init(&pool->queue_ready,NULL);
	pool->queue_head=NULL;
	pool->max_thread_num=max_thread_num;
	pool->cur_queue_size=0;
	pool->shutdown=0;
	pool->threadid = (pthread_t*)malloc(max_thread_num*(sizeof(pthread_t)));
	//创建指定个数的线程
	for (int i = 0; i < max_thread_num; ++i)
	{
		pthread_create(&pool->threadid[i],NULL,thread_routine,NULL);
	}
}

//往任务链表中添加任务结点
int pool_add_worker(void* (*process)(void* arg),void* arg){
	CThread_worker* newworker = (CThread_worker*)malloc(sizeof(CThread_worker));
	newworker->process=process;
	newworker->arg=arg;
	newworker->next=NULL;

	//加锁
	pthread_mutex_lock(&pool->queue_lock);
	CThread_worker*member=pool->queue_head;
	if (member != NULL)//如果头结点不为空,插入链表尾部
	{
		while(member->next != NULL)
			member=member->next;
		member->next=newworker;
	}
	else{//否则头指针指向该结点
		pool->queue_head=newworker;
	}
	assert(pool->queue_head != NULL);
	//任务个数+1
	pool->cur_queue_size++;
	//解锁
	pthread_mutex_unlock(&pool->queue_lock);
	//唤醒至少一个线程
	pthread_cond_signal(&pool->queue_ready);
	return 0;
}

//销毁线程池
int pool_destroy(){
	if(pool->shutdown)
		return -1;

	//如果任务还未做完
	while(pool->cur_queue_size!=0);

	pool->shutdown=1;
	//唤醒全部阻塞在锁前面的线程
	pthread_cond_broadcast(&pool->queue_ready);
	int i;
	for(i=0;i<pool->max_thread_num;i++){
		pthread_join(pool->threadid[i],NULL);
	}
	free(pool->threadid);
	CThread_worker*head=NULL;
	while(pool->queue_head!=NULL){
		head=pool->queue_head;
		pool->queue_head=pool->queue_head->next;
		free(head);
	}
	
	pthread_mutex_destroy(&pool->queue_lock);
	pthread_cond_destroy(&pool->queue_ready);

	free(pool);
	pool=NULL;
	return 0;
}

//线程函数
void* thread_routine(void* arg){
	printf("pthread_self = %lu\n", pthread_self());
	while(1){
		pthread_mutex_lock(&(pool->queue_lock));
		//当任务结点个数为0时阻塞等待
		while(pool->cur_queue_size==0 && !pool->shutdown)
		{
			printf("pthread_self = %lu is waiting\n", pthread_self());
			pthread_cond_wait(&pool->queue_ready,&pool->queue_lock);
		}
		//如果要关闭线程池
		if (pool->shutdown)
		{
			pthread_mutex_unlock(&pool->queue_lock);
			printf("pthread_self = %lu will exit\n", pthread_self());
			pthread_exit(NULL);
		}
		printf("pthread_self = %lu is starting work cur_queue_size =%d\n", 
			pthread_self(),pool->cur_queue_size);

		assert(pool->cur_queue_size!=0);
		assert(pool->queue_head!=NULL);

		//任务链表结点个数-1
		pool->cur_queue_size--;
		//取得任务链表头结点
		CThread_worker*worker=pool->queue_head;
		pool->queue_head=worker->next;
		//解锁
		pthread_mutex_unlock(&pool->queue_lock);

		//?   执行任务函数
		(*(worker->process))(worker->arg);
		//释放该任务结点
		free(worker);
		worker=NULL;
	}
	pthread_exit(NULL);
}

//任务函数
void* myprocess(void *arg){
	printf("pthread_self = %lu\n",pthread_self());

	int port=*(int*)arg;
	int sock;
	struct sockaddr_in addr;
	bzero(&addr,sizeof(addr));
	socklen_t len;
	sock=socket(AF_INET,SOCK_STREAM,0);
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");
	addr.sin_port=htons(port);
	len=sizeof addr;
	int r=connect(sock,(struct sockaddr*)&addr,len);
	if(r==-1)
	{
		printf("pthread_self = %lu connect error\n",pthread_self());
		return NULL;
	}
	char buf[30]={0};
	sprintf(buf,"this is %lu\n",pthread_self());

	if (write(sock,buf,strlen(buf)) != strlen(buf))
	{
		printf("pthread_self = %lu write error\n",pthread_self());
		return NULL;
	}
	r = read(sock,buf,sizeof buf);
	buf[r]='\0';
	printf("pthread_self = %lu read: %s\n",pthread_self(),buf);
	close(sock);

	usleep(5);
	//sleep(1);
	return NULL;
}

int main(int argc,char* argv[]){

	if (argc!=4)
	{
		printf("use: port + pthread_num + work_num\n");
		return 1;
	}


	pool_init(atoi(argv[2]));

	int port = atoi(argv[1]);
	int worknum = atoi(argv[3]);

	for (int i = 0; i < worknum; ++i)
	{
		pool_add_worker(myprocess,&port);
	}
	pool_destroy();

	return 0;

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值