Linux网络编程——线程池模型

Linux网络编程——线程池模型


前言

线程池创建代码参考博客:https://blog.csdn.net/weixin_38956024/article/details/107892958

一、线程池主要函数说明

threadpool_t* threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size)
//创建一个线程池
//min_thr_num:线程池中最少存活的线程数量
//max_thr_num:线程池的最大容量
//queue_max_size:任务队列的最大数量
//返回值:指向一个线程池的指针。

int threadpool_add(threadpool_t *pool, void *(*function)(void *arg), void *arg)
//向线程池的任务队列中添加队列
//pool:指定的线程池
//func:函数指针,指向真正处理事务的函数
//arg:func的参数
//返回值:成功(0);失败(-1)

void *threadpool_thread(void *threadpool)
//任务线程调用的函数

void *adjust_thread(void *threadpool)
//管理线程使用的函数

int threadpool_destroy(threadpool_t *pool)
int threadpool_free(threadpool_t *pool)
//线程池的的销毁和释放函数

void *process(void *arg)
//真正完成任务的函数

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、代码实现

#include <iostream>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>

#define DEFAULT_TIME 10
#define MIN_WAIT_TASK_NUM 10
#define DEFAULT_THREAD_VARY 10
#define true 1
#define false 0
#define SERV_PORT 9999

using namespace std;

typedef struct
{
        void *(*function)(void *);
        void *arg;                                               //the parameter of function
} threadpool_task_t;

//the struct of threadpool
struct threadpool_t
{
        pthread_mutex_t  lock;                      //the lock of threadpool_t
        pthread_mutex_t  thread_counter;  //busy thread number

        pthread_cond_t queue_not_full;   //when the task queue is full, we need to wait it not full to add task thread
        pthread_cond_t queue_not_empty; //when the task queue isn't empty, notice the waiting task thread

        pthread_t *threads;     //the array of thread's tid
        pthread_t adjust_tid;  //the administration thread's tid
        threadpool_task_t *task_queue; // the array of task queue

        int min_thr_num;            //the min_thr_num in threadpool
        int max_thr_num;            //the max_thr_num in threadpool
        int live_thr_num;            //the live_thr_num in threadpool
        int busy_thr_num;            //the busy_thr_num in threadpool
        int wait_exit_thr_num;            //the number of thread who will be destory(exit)

        int queue_front;                    //the task queue's head
        int queue_rear;                     //the task queue's tail
        int queue_size;                     //the task queue's current size
        int queue_max_size;                 //the task queue's capacity

        int shutdown;                  //flag: the using state of threadpool, its value is true(shutdown) or false(not 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)
{
        threadpool_t *pool = NULL;

        do
        {
                if((pool = new threadpool_t) == NULL)
                {
                        cout << "new threadpool is fail" <<endl;
                        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;

                //malloc space for task thread
                pool->threads = new pthread_t[max_thr_num];
                if(pool->threads == NULL)
                {
                        cout << "new pthread_t[max_thr_num] fail"<<endl;
                        break;
                }

                //malloc task queue space
                pool->task_queue = new threadpool_task_t[queue_max_size];
                if(pool->task_queue == NULL)
                {
                        cout << "new task_queue fail"<<endl;
                        break;
                }

                if(pthread_mutex_init(&pool->lock,NULL) != 0
                        || pthread_mutex_init(&pool->thread_counter,NULL) != 0
                        || pthread_cond_init(&pool->queue_not_full,NULL)    != 0
                        || pthread_cond_init(&pool->queue_not_empty,NULL) != 0)
                {
                        cout << "init the mutex or cond fail"<<endl;
                        break;
                }

                for(int i = 0; i <min_thr_num; i++)
                {
                        pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void*)pool);
                        cout << "start thread " << (unsigned int)pool->threads[i]<<endl;
                }

                pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void *)pool);

                return pool;
        }while(0);

        return NULL;
}

//add a task to threadpool
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);
        }

        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;
        }

        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;
}

//the working thread in threadpool
void *threadpool_thread(void *threadpool)
{
        threadpool_t *pool = (threadpool_t *)threadpool;
        threadpool_task_t task;

        while(1)
        {
                pthread_mutex_lock(&pool->lock);

                while((pool->queue_size == 0) && (!pool->shutdown))
                {
                        cout<<"thread "<< (unsigned int)pthread_self() << "is waiting"<<endl;
                        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)
                                {
                                        cout << "thread " << (unsigned int)pthread_self() << "is exiting...." <<endl;
                                        pool->live_thr_num-- ;
                                        pthread_mutex_unlock(&pool->lock);

                                        pthread_exit(NULL);
                                }
                        }
                }

                if(pool->shutdown)
                {
                        pthread_mutex_unlock(&pool->lock);
                        cout << "thread " <<(unsigned int)pthread_self() << "is exiting"<<endl;
                        pthread_detach(pthread_self());
                        pthread_exit(NULL);
                }

                task.function = pool->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);

                cout << "thread " << (unsigned int)pthread_self() << "is working!" <<endl;
                pthread_mutex_lock(&pool->thread_counter);
                pool->busy_thr_num++;
                pthread_mutex_unlock(&pool->thread_counter);

                (*(task.function))(task.arg);

                cout << "thread " << (unsigned int)pthread_self() << "end working" <<endl;
                pthread_mutex_lock(&pool->thread_counter);
                pool->busy_thr_num --;
                pthread_mutex_unlock(&pool->thread_counter);
        }
        pthread_exit(NULL);
}

//the administration's work thread function
void *adjust_thread(void *threadpool)
{
        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 = pool->live_thr_num;
                pthread_mutex_unlock(&pool->lock);

                pthread_mutex_lock(&pool->thread_counter);
                int busy_thr_num = pool->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(int 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->threads[i], NULL, threadpool_thread, (void*)pool);
                                        add++;
                                        pool->live_thr_num++;
                                }
                        }

                pthread_mutex_unlock(&pool->lock);
                }

                if((busy_thr_num * 2) < pool->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(int i = 0; i < DEFAULT_THREAD_VARY; i++)
                        {
                                pthread_cond_signal(&pool->queue_not_empty);
                        }
                }

        }

        return NULL;
}

//destroy threadpool
int threadpool_destroy(threadpool_t *pool)
{
        if(pool == NULL)
        {
                return -1;
        }

        pool->shutdown = true;

        pthread_join(pool->adjust_tid, NULL);

        for(int i = 0; i < pool->live_thr_num; i++)
        {
                pthread_cond_broadcast(&pool->queue_not_empty);
        }

        for(int i = 0; i < pool->live_thr_num; i++)
        {
                pthread_join(pool->threads[i], NULL);
        }

        threadpool_free(pool);

        return 0;
}

//free threadpool
int threadpool_free(threadpool_t *pool)
{
        if(pool == NULL)  return -1;

        if(pool->task_queue)  delete pool->task_queue;

        if(pool->threads)
        {
                delete 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_full);
                pthread_cond_destroy(&pool->queue_not_empty);
        }

        delete pool;
        pool =  NULL;

        return 0;
}

int threadpool_all_threadnum(threadpool_t *pool)
{
    int all_threadnum = -1;                

    pthread_mutex_lock(&(pool->lock));
    all_threadnum = pool->live_thr_num;    
    pthread_mutex_unlock(&(pool->lock));

    return all_threadnum;
}

int threadpool_busy_threadnum(threadpool_t *pool)
{
    int busy_threadnum = -1;                

    pthread_mutex_lock(&(pool->thread_counter));
    busy_threadnum = pool->busy_thr_num;    
    pthread_mutex_unlock(&(pool->thread_counter));

    return busy_threadnum;
}

//judge a thread is alive or not
int is_thread_alive(pthread_t tid)
{
        int kill_rc = pthread_kill(tid, 0);
        if(kill_rc == ESRCH)
        {
                return false;
        }

        return true;
}


void *process(void *arg)
{
        //cout << "thread "<<pthread_self() << "working on task " << *((int *)arg) << endl;
        //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);
        //cout << "task " << *((int *)arg)  << "is end!" <<endl;

        //close(lfd);
        int connfd = *((int*)arg);
        cout << "In threead " << pthread_self() << ", connfd=" << connfd << endl;
        int nread;
        char buf[1024];

        while(1)
        {
                nread = recv(connfd, buf, sizeof(buf), 0);
                if(nread == -1)
                {
                        perror("recv error");
                        close(connfd);
                        break;
                }

                else if (nread == 0)
                {
                        cout << "------the have disconneted!------"<<endl;
                        close(connfd);
                        break;
                }

                else if(nread > 0)
                {
                        for(int i = 0; i < nread; i++)
                        {
                                buf[i] = toupper(buf[i]);
                        }

                        send(connfd, buf, nread, 0);
                }

        }

        return NULL;
}

int main(void)
{
    /*threadpool_t *threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size);*/

        threadpool_t *thp = threadpool_create(3,100,100);   /*创建线程池,池里最小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);
        
//         /*int threadpool_add(threadpool_t *pool, void*(*function)(void *arg), void *arg) */

//         threadpool_add(thp, process, (void*)&num[i]);   /* 向线程池中添加任务 */
//     }

        int lfd = socket(AF_INET,SOCK_STREAM, 0);
        
        struct sockaddr_in serv_addr;
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SERV_PORT);
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        int ret = bind(lfd, (sockaddr*)&serv_addr, sizeof(serv_addr));
        if(ret == -1)
        {
                perror("bind error");
                exit(1);
        }

        ret = listen(lfd, 256);
        if(ret == -1)
        {
                perror("listen error");
                exit(1);
        }

        int connfd;
        struct sockaddr_in client_addr;
        socklen_t client_addr_len = sizeof(client_addr);

        while(1)
        {
                connfd = accept(lfd, (sockaddr*)&client_addr, &client_addr_len);
                if(connfd == -1)
                {
                        perror("accept error");
                        exit(1);
                }

                else
                {
                        cout << "connfd="<<connfd<<endl;
                        threadpool_add(thp, process, (void*)&connfd); 
                }
        }



        //sleep(10);                                          /* 等子线程完成任务 */
        threadpool_destroy(thp);

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值