线程池,根据命令行参数,传递连接的端口号,线程个数,任务个数(即连接次数)
可以测试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;
}