[C/C++] 线程池的简单实现

1.何为线程池。

把线程池想象成食堂打饭阿姨,每一份饭对应一个线程,线程池的作用便是像打饭阿姨一样在没人的时候等待,一旦有人刷卡(任务到来),阿姨便分发餐盘打菜(分配线程),吃完后再回收餐盘(回收线程)继续等待。当然,阿姨一怒之下也可以把餐盘摔了(结束线程)。同时可能有几个窗口(临界资源)进行打饭,所以不可避免的要加锁。

2.线程池的作用。

个人理解,线程池起到一个缓冲区的作用,等需要的时候从池子里拿,不要再放回,避免线程创建销毁的过渡开销,同时对线程起到一个管理作用。以及很重要的异步解耦(异步io)的作用。

3.代码

整个线程池大致分为这几个部分。

线程池创建销毁,添加任务,线程回调函数组成。而线程池的每个线程,和任务采用双向链表的方式存储。

#include <iostream>
#include <cstring>
#include <pthread.h>

template<class T>              
void LL_ADD(T &item, T &list){   // head insert
    item->prev = NULL;
    item->next = list;
    if (list!=NULL)
        list->prev = item;
    list = item;
}

template<class T>
void LL_REMOVE(T &item, T &list){
    if (item->prev != NULL)
        item->prev->next = item->next;
    if (item->next != NULL) 
        item->next->prev =  item->prev;
    if (list == item)
        list = item->next;
    item->prev = item->next = NULL;
}

struct N_WORKER{    //线程双链表
    
    pthread_t thread;
    struct N_MANAGER *pool;
    int terminate;            //线程终止标致位

    struct N_WORKER *prev;
    struct N_WORKER *next;
};

struct N_JOB{          //任务双链表
    
    void (*func)(int data, pthread_t threadId);   //每个任务对应的任务函数 可自己修改
    int user_data;                                //任务数据

    struct N_JOB *prev;
    struct N_JOB *next;

};

struct N_MANAGER{                    //管理
    
    struct N_WORKER *workers;
    struct N_JOB *jobs;
    
    pthread_cond_t jobs_cond;      //条件变量 线程等待某个条件的满足否则挂起
    pthread_mutex_t jobs_mutex;  //锁


};

typedef struct N_MANAGER nThreadPool;

static void *nThreadCallBack(void *arg){  //本文件有效
    struct N_WORKER *worker = (struct N_WORKER*)arg;
    while (1){
        pthread_mutex_lock(&worker->pool->jobs_mutex);  //加锁
        while(worker->pool->jobs == NULL){   //无任务
            if(worker->terminate) break;    //线程是否要求终止
            pthread_cond_wait(&worker->pool->jobs_cond, &worker->pool->jobs_mutex);  //函数里解锁,函数结束加锁,执行代码不在锁内 有风险
        }
        if(worker->terminate){
            pthread_mutex_unlock(&worker->pool->jobs_mutex);   //解锁
            break;
        }

        struct N_JOB *job = worker->pool->jobs;
        LL_REMOVE(job, worker->pool->jobs);  //有任务时 取出一个任务 头结点

        pthread_mutex_unlock(&worker->pool->jobs_mutex);   //解锁
        
        job->func(job->user_data, worker->thread);   //任务执行函数
    }
    free(worker);
    pthread_exit(NULL);
}



//Thread Pool Create, API
int nThreadPoolCreate(nThreadPool *pool, int numWorkers){
    
    if(numWorkers < 1) numWorkers = 1;
    if(pool == NULL) return -1;
    memset(pool, 0, sizeof(nThreadPool));       //init pool
    
    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->jobs_cond, &blank_cond, sizeof(pthread_cond_t));    //init jobs_cond
   
    pthread_mutex_t blank_mutex = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->jobs_mutex, &blank_mutex, sizeof(pthread_mutex_t));   //init jobs_mutex

    for(int i = 0; i < numWorkers; i++){                             //创建线程加入线程池
        struct N_WORKER *worker = (struct N_WORKER *)malloc(sizeof(struct N_WORKER));
        if(worker == NULL){
            perror("new");
            return -2;
        }
        memset(worker, 0, sizeof(struct N_WORKER));               //init
        worker->pool = pool;
        int ret = pthread_create(&worker->thread, NULL, nThreadCallBack, worker);  //创建线程
        if(ret){
            perror("pthread_create");
            return -3;
        }
        LL_ADD(worker,pool->workers);  //加入线程池
    }
}

void nThreadPoolPush(nThreadPool *pool, struct N_JOB *job){     //添加任务
    
    pthread_mutex_lock(&pool->jobs_mutex);
    LL_ADD(job, pool->jobs);                      //添加
    pthread_cond_signal(&pool->jobs_cond);  // 唤醒 line:70
    pthread_mutex_unlock(&pool->jobs_mutex);
}

int nThreadPoolDestory(nThreadPool *pool){
    struct N_WORKER *worker = NULL;
    for(worker = pool->workers; worker != NULL; worker = worker->next){
        worker->terminate = 1;            // 让每个线程终止标致位置1
    }
    pthread_mutex_lock(&pool->jobs_mutex);
    pthread_cond_broadcast(&pool->jobs_cond);
    pthread_mutex_unlock(&pool->jobs_mutex);
}
void Job_func(int data ,pthread_t threadId){
    
    std::cout<<"id:"<<threadId<<"->"<<data<<std::endl;
}

int main(){
    
    nThreadPool *pool;
    nThreadPoolCreate(pool, 1000);

    for(int i = 0; i < 1000; i++){
           struct N_JOB *job = (struct N_JOB*)malloc(sizeof(struct N_JOB));
           job->func = Job_func;
           job->user_data = i;
           nThreadPoolPush(pool, job);
    }
    nThreadPoolDestory(pool);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值