一个简单线程池的实现 --C语言

来源:互联网 发布:党员干部必知的50个词 编辑:程序博客网 时间:2024/04/25 17:43

本文的代码实现了一个简单的线程池,并利用C/S模型将客户端所发送的数据进行简单的计算。

一:什么是线程池

  我是这么理解的,池是计算机科学中一种典型的机制,如STL里面的内存池,数据库连接池,还有进程池或线程池。这些池建立的目的都是为了避免频繁系统调用所带来的开销。我们这样想,如果我们事先转备好一大块所需要的内存,或者线程,以后我们要用到时就直接拿来用就好了。不够的话再执行其他解决方案。

二:本文代码线程池实现细节

  在本文代码中,定义了一个线程池线程数组,线程池水深(线程数)假定为5,这个值我们根据实际情况选择。我们可以事先申请5个线程,让他们在各自的线程运行函数内部循环,这就相当于block,但不是block。当我们需要线城时,直接拿来主义,让该线程的WORK_STATE为BUSY态,这是全局结构体变量,当检测到此情况出现,线程run,这就是线程池的分配过程。

  线程池回收,将BUSY态改为IDLE态即可,继续循环。

  如果线程池不够用,我对额外线程采用的机制是,来一个申请一个,走一个销毁一个。

三:头文件

#pragma once#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <assert.h>#include <errno.h>#include <pthread.h>#include <sys/socket.h>#include <sys/types.h>#include <arpa/inet.h>#include <netinet/in.h>#include <stdbool.h>#define INIT_THREAD_NUM 5#define MAXLINE 1024#define err_quit(m) \do{ \perror(m); \exit(1); \}while(0)typedef enum{IDLE, BUSY}WORK_STATE;typedef enum{ADD, SUB, MUL, DIV, MOD}OPER_ENUM;typedef struct {int       op1;int       op2;OPER_ENUM oper;}oper_struct;

四:服务器代码

#include "../utili.h"void math_operation(oper_struct *ptr, int *res);static void* extra_thread_handler(void *arg);static void* pool_thread_handler(void *arg);bool find_idle_thread(int connfd);typedef struct thread_extra {   int index;int connfd;} thread_extra;    //额外线程结构体typedef struct thread_pool {int        connfd;WORK_STATE state;} thread_pool;     //线程池结构体typedef thread_pool pool_array[INIT_THREAD_NUM];    //线程池线程数组pool_array pool;int extra_num;     //额外数目,用来计算额外线程序号int main(){int listenfd;struct sockaddr_in servaddr;if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)err_quit("socket err.\n");memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(6666);servaddr.sin_addr.s_addr = INADDR_ANY;int on = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)err_quit("bind err.\n");if(listen(listenfd, SOMAXCONN) < 0)err_quit("listen err.\n");int connfd;struct sockaddr_in clientaddr;socklen_t len = sizeof(clientaddr);pthread_t tid_array[INIT_THREAD_NUM];for(int i=0; i<INIT_THREAD_NUM; ++i){pthread_create(&tid_array[i], NULL, pool_thread_handler, &i);sleep(1);}for(int i=0; i<INIT_THREAD_NUM; ++i){pool[i].state = IDLE;}pthread_t tid;thread_extra th_extra;for(; ;){if( (connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &len)) < 0)err_quit("accept err.\n");elseprintf("client: IP:%s PORT:%d connect.\n", inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));if(!find_idle_thread(connfd)){++extra_num;th_extra.index = INIT_THREAD_NUM + extra_num - 1;th_extra.connfd = connfd;pthread_create(&tid, NULL, extra_thread_handler, &th_extra);}}return 0;}bool find_idle_thread(int connfd){for(int i=0; i<INIT_THREAD_NUM; ++i){if(pool[i].state == IDLE){pool[i].state = BUSY;pool[i].connfd = connfd; return true;}}return false;}static void* pool_thread_handler(void *arg){pthread_detach(pthread_self());int index = *(int *)arg;printf("[%d] thread start up.\n", index);int         res;ssize_t     nrecv;oper_struct ops;for(; ;){for(; ;){if(pool[index].state == BUSY){printf("[%d] thread provide service.\n", index);if( (nrecv = recv(pool[index].connfd, &ops, sizeof(ops), 0)) == 0){printf("peer close,[%d] thread to have a rest.\n", index);break;}math_operation(&ops, &res);printf("the result is:%d\n", res);send(pool[index].connfd, &res, sizeof(res), 0);}}pool[index].state = IDLE;             //线程回收close(pool[index].connfd);}return (void *)0;}static void* extra_thread_handler(void *arg){pthread_detach(pthread_self());int index = *(int *)arg;int connfd = *((int *)arg+1);printf("[%d] thread start up.\n", index);int         res;ssize_t     nrecv;oper_struct ops;for(; ;){printf("[%d] thread provide service.\n", index);if( (nrecv = recv(connfd, &ops, sizeof(ops), 0)) == 0){printf("peer close,[%d] thread go to dead.\n", index);break;}math_operation(&ops, &res);printf("the result is:%d\n", res);send(connfd, &res, sizeof(res), 0);}--extra_num;close(connfd);return (void *)0;}void math_operation(oper_struct *ptr, int *res){switch(ptr->oper){case ADD:*res = ptr->op1 + ptr->op2;break;case SUB:*res = ptr->op1 - ptr->op2;break;case MUL:*res = ptr->op1 * ptr->op2;break;case DIV:*res = ptr->op1 / ptr->op2;break;case MOD:*res = ptr->op1 % ptr->op2;break;default: break;}}

五:客户端代码

#include "../utili.h"void input_opernum(oper_struct *pointer);int main(){int sockfd;struct sockaddr_in servaddr;if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)err_quit("socket err.\n");memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(6666);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)err_quit("connect err.\n");oper_struct ops;char *symbol;char recvbuff[MAXLINE];for( ; ;){printf("please input operator symbol:>\n");scanf("%s", symbol);if(strncmp(symbol, "add", 3) == 0){ops.oper = ADD;input_opernum(&ops);}else if(strncmp(symbol, "sub", 3) == 0){ops.oper = SUB;input_opernum(&ops);}else if(strncmp(symbol, "mul", 3) == 0){ops.oper = MUL;input_opernum(&ops);}else if(strncmp(symbol, "div", 3) == 0){ops.oper = DIV;input_opernum(&ops);}else if(strncmp(symbol, "mod", 3) == 0){ops.oper = MOD;input_opernum(&ops);}else{printf("invilid input.\n");continue;}send(sockfd, &ops, sizeof(ops), 0);recv(sockfd, recvbuff, sizeof(int), 0);printf("the answer is:>%d\n", *(int*)recvbuff);}close(sockfd);return 0;}

*所有程序均经过验证。

0 0