手写线程池与性能分析

一、为什么要使用线程池?

1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2.提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3.提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

二、线程池的工作原理

在这里插入图片描述

三、nginx中使用线程池的场景举例

在这里插入图片描述
在这里插入图片描述

四、实现线程池的功能组件

1、执行(线程ID、终止标识、池管理组件对象);
在这里插入图片描述

2、任务(任务的回调函数、任务执行的参数);
在这里插入图片描述

3、池管理组件(互斥锁、条件变量、执行队列、任务队列);
在这里插入图片描述

五、线程池的具体代码实现

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h> 
#include <time.h> 

#define KING_MAX_THREAD			10
#define KING_COUNTER_SIZE		100

typedef struct queue_job{
    void (*job_function_hdl)(struct queue_job *job);
    void *user_data;
    struct queue_job *next;
    struct queue_job *prev;
}nJob_t;

typedef struct thread_worker{
    pthread_t tid;
    int termainate;
    struct thread_pool *pool;
    struct thread_worker *next;
    struct thread_worker *prev;
}nWorker_t;

typedef struct thread_pool{
    nWorker_t *workers;
    nJob_t *waiting_jobs;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}nThreadPool_t;


#define LL_ADD_HEAD(item, list) do{ \
    item->prev = NULL;               \
    item->next = list;              \
    if(list != NULL) list->prev = item; \
    list = item;                     \
}while(0)

#define LL_REMOVE_LIST(item, list) do{  \
    if(item->prev != NULL) item->prev->next = item->next;   \
    if(item->next != NULL) item->next->prev = item->prev;   \
    if(item == list) list = list->next; \
    item->prev = NULL;  \
    item->next = NULL;  \
}while(0)


//消费者线程
void *nThreadWorkerHdl(void *arg){
    nWorker_t *new_worker = (nWorker_t *)arg;

    while(1){
        pthread_mutex_lock(&new_worker->pool->mutex);
        while(new_worker->pool->waiting_jobs == NULL){
            //销毁线程池使用的
            if(new_worker->termainate) break;
            pthread_cond_wait(&new_worker->pool->cond, &new_worker->pool->mutex);
        }

        if(new_worker->termainate){
            pthread_mutex_unlock(&new_worker->pool->mutex);
            break;
        }

        nJob_t *job = new_worker->pool->waiting_jobs;
        if(job != NULL){
            LL_REMOVE_LIST(job, new_worker->pool->waiting_jobs);
        }
        pthread_mutex_unlock(&new_worker->pool->mutex);

        if(job == NULL) continue;

        job->job_function_hdl(job);        
    }

    //if(new_worker){
        //free(new_worker);
    //}
    pthread_exit(NULL);
}

int ntyMainThreadJoin(nThreadPool_t *pool){
    if(pool == NULL) return -1;

    nWorker_t *worker = pool->workers;
    nWorker_t *ptr = NULL;
    
    while(worker != NULL){
        printf("回收子线程:%lu\n",worker->tid);
        pthread_join(worker->tid, NULL);
        ptr = worker->next;
        free(worker);
        worker = ptr;
    }
    return 0;
}

int ntyThreadPoolDestory(nThreadPool_t *pool) {
    if(pool == NULL) return -1;
    
	nWorker_t *worker = NULL;

	for (worker = pool->workers; worker != NULL;worker = worker->next) {
		worker->termainate = 1;
	}

	pthread_mutex_lock(&pool->mutex);
    //这块的释放放在线程池销毁的函数中进行
	//pool->workers = NULL; 
	pool->waiting_jobs = NULL;
	pthread_cond_broadcast(&pool->cond);

	pthread_mutex_unlock(&pool->mutex);

    ntyMainThreadJoin(pool);

    return 0;
}


//生产者线程,生产完消息后,通过条件变量唤醒阻塞在条件变量上的消费者线程
void nThreadPoolPushTask(nThreadPool_t *pool, nJob_t *new_job){
    pthread_mutex_lock(&pool->mutex);
    
    LL_ADD_HEAD(new_job, pool->waiting_jobs);
    pthread_cond_broadcast(&pool->cond);
    pthread_mutex_unlock(&pool->mutex);
    return ;
}

int thread_pool_create(nThreadPool_t *pool, int thread_workers){
    if(pool == NULL) return -1;
    int idx = 0;
    int ret;
    if(thread_workers < 1)  thread_workers = 1;
    memset(pool, 0, sizeof(nThreadPool_t));

    //pool->cond = PTHREAD_COND_INITIALIZER;
    //pool->mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->cond, &cond, sizeof(pthread_cond_t));

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->mutex, &mutex, sizeof(pthread_mutex_t));

    for(idx = 0; idx < thread_workers; idx++){
        nWorker_t *new_worker = (nWorker_t*)malloc(sizeof(nWorker_t));
        if(NULL == new_worker){
            perror("malloc():");
            return -1;
        }

        memset(new_worker, 0, sizeof(nWorker_t));
        new_worker->pool = pool;

        ret = pthread_create(&new_worker->tid, NULL, nThreadWorkerHdl, (void *)new_worker);
        if(ret < 0){
            perror("phtread_create():");
            free(new_worker);
            return idx;
        }
        //设置线程分离,不需要父进程回收
        //pthread_detach(new_worker->tid);
        LL_ADD_HEAD(new_worker, new_worker->pool->workers);  
    }

    //返回创建成功的线程个数
    return idx; 
}

void king_counter_hdl(nJob_t *job){
     int index = *(int*)job->user_data;
     printf("index : %d, selfid : %lu\n", index, pthread_self());

    free(job->user_data);
    free(job);
}

int main(int argc, char *argv[]){
    nThreadPool_t pool;
    int i;

    //这个是创建的多个消费者线程,形成线程池,消费处理任务
    memset(&pool, 0, sizeof(nThreadPool_t));
    thread_pool_create(&pool, KING_MAX_THREAD);

    //这个是主控线程,作为生产者生产消息
    for(i = 0; i < KING_COUNTER_SIZE; i++){
         nJob_t *new_job = (nJob_t *)malloc(sizeof(nJob_t));
         if(new_job == NULL){
            perror("malloc():");
            return -1;
         }
         new_job->job_function_hdl = king_counter_hdl;
         new_job->user_data = (int *)malloc(sizeof(int));
         *(int *)new_job->user_data = i;
         
         nThreadPoolPushTask(&pool, new_job);
    }

    //睡眠十秒钟等待任务队列被执行完成
    sleep(10);    
    printf("睡眠十秒钟等待任务队列被执行完成\n");

    //线程池销毁
    ntyThreadPoolDestory(&pool);

    return 0;
}

代码调试执行:
[root@localhost c++_test]# gcc my_pthread_pool.c -o test -lpthread
[root@localhost c++_test]# ./test
index : 99, selfid : 140216515962624
index : 96, selfid : 140216515962624
index : 95, selfid : 140216515962624
index : 94, selfid : 140216515962624
index : 93, selfid : 140216515962624
index : 92, selfid : 140216515962624
index : 91, selfid : 140216515962624
index : 90, selfid : 140216515962624
index : 89, selfid : 140216515962624
index : 88, selfid : 140216515962624
index : 87, selfid : 140216515962624
index : 86, selfid : 140216515962624
index : 85, selfid : 140216515962624
index : 84, selfid : 140216515962624
index : 83, selfid : 140216515962624
index : 82, selfid : 140216515962624
index : 81, selfid : 140216515962624
index : 80, selfid : 140216515962624
index : 79, selfid : 140216515962624
index : 78, selfid : 140216515962624
index : 77, selfid : 140216515962624
index : 76, selfid : 140216515962624
index : 75, selfid : 140216515962624
index : 74, selfid : 140216515962624
index : 73, selfid : 140216515962624
index : 72, selfid : 140216515962624
index : 71, selfid : 140216515962624
index : 70, selfid : 140216515962624
index : 69, selfid : 140216515962624
index : 68, selfid : 140216515962624
index : 67, selfid : 140216515962624
index : 66, selfid : 140216515962624
index : 65, selfid : 140216515962624
index : 64, selfid : 140216515962624
index : 63, selfid : 140216515962624
index : 97, selfid : 140216499177216
index : 61, selfid : 140216499177216
index : 60, selfid : 140216499177216
index : 62, selfid : 140216515962624
index : 58, selfid : 140216490784512
index : 56, selfid : 140216490784512
index : 55, selfid : 140216490784512
index : 54, selfid : 140216490784512
index : 98, selfid : 140216507569920
index : 53, selfid : 140216490784512
index : 52, selfid : 140216490784512
index : 50, selfid : 140216490784512
index : 49, selfid : 140216490784512
index : 48, selfid : 140216490784512
index : 47, selfid : 140216490784512
index : 46, selfid : 140216490784512
index : 45, selfid : 140216490784512
index : 59, selfid : 140216499177216
index : 43, selfid : 140216482391808
index : 51, selfid : 140216507569920
index : 39, selfid : 140216507569920
index : 38, selfid : 140216507569920
index : 37, selfid : 140216507569920
index : 36, selfid : 140216507569920
index : 35, selfid : 140216507569920
index : 34, selfid : 140216507569920
index : 33, selfid : 140216507569920
index : 32, selfid : 140216507569920
index : 31, selfid : 140216507569920
index : 30, selfid : 140216507569920
index : 29, selfid : 140216507569920
index : 28, selfid : 140216482391808
index : 26, selfid : 140216465606400
index : 24, selfid : 140216465606400
index : 23, selfid : 140216465606400
index : 22, selfid : 140216465606400
index : 21, selfid : 140216465606400
index : 20, selfid : 140216465606400
index : 19, selfid : 140216465606400
index : 18, selfid : 140216465606400
index : 17, selfid : 140216465606400
index : 16, selfid : 140216465606400
index : 57, selfid : 140216515962624
index : 27, selfid : 140216507569920
index : 12, selfid : 140216507569920
index : 11, selfid : 140216507569920
index : 10, selfid : 140216507569920
index : 9, selfid : 140216507569920
index : 8, selfid : 140216507569920
index : 7, selfid : 140216507569920
index : 6, selfid : 140216507569920
index : 5, selfid : 140216507569920
index : 4, selfid : 140216507569920
index : 3, selfid : 140216507569920
index : 2, selfid : 140216507569920
index : 1, selfid : 140216507569920
index : 0, selfid : 140216507569920
index : 42, selfid : 140216473999104
index : 40, selfid : 140216457213696
index : 25, selfid : 140216482391808
index : 44, selfid : 140216490784512
index : 15, selfid : 140216448820992
index : 14, selfid : 140216465606400
index : 13, selfid : 140216515962624
index : 41, selfid : 140216499177216
睡眠十秒钟等待任务队列被执行完成
回收子线程:140216440428288
回收子线程:140216448820992
回收子线程:140216457213696
回收子线程:140216465606400
回收子线程:140216473999104
回收子线程:140216482391808
回收子线程:140216490784512
回收子线程:140216499177216
回收子线程:140216507569920
回收子线程:140216515962624

以上就是我对线程池的理解实现,有什么不明白之处请在评论区留言,我们一起讨论学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值