C 线程池

8 篇文章 0 订阅

参考 <https://blog.csdn.net/qq_36359022/article/details/78796784>

参考 <https://www.bilibili.com/video/BV1iJ411S7UA>

看了大概的思路,自己理解着敲一下,然后对比原来代码有些地方不同。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include <pthread.h>

#include <errno.h>

#include <time.h>

#define DEFAULT_TIME 1

typedef struct{
    void* (*function)(void *);
    void *arg;
}threadpoll_task_t;

typedef struct{
    pthread_t thr_maneger;//管理线程
    int thr_maneger_exit;//管理线程状态

    pthread_mutex_t thr_mutex;//线程组
    pthread_t *thr;//线程的锁
    int thr_min_num;//最低
    int thr_max_num;//最高
    int thr_cap_num;//线程数
    int thr_len_num;//线程活跃数

    pthread_mutex_t task_mutex;//任务的锁
    pthread_cond_t task_cond;//任务的条件变量
    threadpoll_task_t *task_queue;//任务队列,环
    int task_cap_num;//任务队列容量
    int task_len_num;//任务队列的任务数
    int task_head_index;//头
    int task_tail_index;//尾
    int task_suicide;//自杀式任务数
}threadpool_t;


void* threadpool_thread(void *arg){
    threadpool_t *pool = (threadpool_t*)arg;

    for(;;){
        pthread_mutex_lock(&pool->task_mutex);
        while(pool->task_len_num <=0 && pool->task_suicide <= 0)
            pthread_cond_wait(&pool->task_cond,&pool->task_mutex);
        
        //如果有自杀式任务,则自杀
        if(pool->task_suicide > 0){
            pool->task_suicide--;
            pthread_mutex_unlock(&pool->task_mutex);
            break;
        }

        //从任务队列中取数据
        void* (*function)(void *);
        void *arg;
        function = pool->task_queue[pool->task_tail_index].function;
        arg = pool->task_queue[pool->task_tail_index].arg;
        pool->task_tail_index = (pool->task_tail_index+1) % pool->task_cap_num;
        pool->task_len_num--;
        pthread_mutex_unlock(&pool->task_mutex);

        //活跃线程数+1
        pthread_mutex_lock(&pool->thr_mutex);
        pool->thr_len_num++;
        pthread_mutex_unlock(&pool->thr_mutex);
        function(arg);

        //活跃线程数-1
        pthread_mutex_lock(&pool->thr_mutex);
        pool->thr_len_num--;
        pthread_mutex_unlock(&pool->thr_mutex);

        //唤醒可能阻塞中的task_add
        pthread_cond_broadcast(&pool->task_cond);
    }

    pthread_exit(NULL);
}

int is_thread_alive(pthread_t tid){
    int kill_rc = pthread_kill(tid,0);
    if(kill_rc == ESRCH){
        return 0;
    }
    return 1;
}

void *threadpoll_admin(void *arg){
    threadpool_t *pool = (threadpool_t*)arg;
    int thr_min_num;
    int thr_max_num;
    int thr_cap_num,new_thr_cap_num;
    int thr_len_num;
    int task_len_num;
    int task_suicide;
    int count,i;
    
    pthread_mutex_lock(&pool->thr_mutex);
    thr_min_num = pool->thr_min_num;
    thr_max_num = pool->thr_max_num;
    pthread_mutex_unlock(&pool->thr_mutex);

    for(;;){
        sleep(DEFAULT_TIME);

        //判断管理线程是否需要退出
        if(pool->thr_maneger_exit == 1){
            break;
        }

        //取数据
        pthread_mutex_lock(&pool->thr_mutex);
        thr_cap_num = pool->thr_cap_num;
        thr_len_num = pool->thr_len_num;
        pthread_mutex_unlock(&pool->thr_mutex);

        pthread_mutex_lock(&pool->task_mutex);
        task_len_num = pool->task_len_num;
        task_suicide = pool->task_suicide;
        pthread_mutex_unlock(&pool->task_mutex);

        printf("pool status "
        ",thr_cap_num=%d "
        ",thr_len_num=%d "
        ",task_len_num=%d "
        ",task_suicide=%d "
        "\n",
        thr_cap_num,thr_len_num,task_len_num,task_suicide);

        //还没自杀完
        if(task_suicide > 0){
            continue;
        }

        //线程活跃数占80%,扩容
        if(thr_len_num >= thr_cap_num * 0.8){//扩容
            new_thr_cap_num = thr_cap_num*2;
            if(new_thr_cap_num>thr_max_num){
                new_thr_cap_num = thr_max_num;
            }
            count = new_thr_cap_num - thr_cap_num;
            if(count <= 0)
                continue;

            pthread_mutex_lock(&pool->thr_mutex);
            pool->thr_cap_num = new_thr_cap_num;
            pthread_mutex_unlock(&pool->thr_mutex);

            for(i=0;i<thr_max_num && count>0;i++){
                //判断是否是自杀线程,回收
                if(pool->thr[i] != 0 && !is_thread_alive(pool->thr[i])){
                    pthread_join(pool->thr[i],NULL);
                    pool->thr[i] = 0;
                }

                //创建线程
                if(pool->thr[i] == 0){
                    pthread_create(&pool->thr[i],NULL,threadpool_thread,(void*)pool);
                    count--;
                }
            }
            continue;
        }

        //线程活跃数占20%,缩容
        if(thr_len_num <= thr_cap_num * 0.2){//缩容
            new_thr_cap_num = thr_cap_num/2;
            if(new_thr_cap_num<thr_min_num){
                new_thr_cap_num = thr_min_num;
            }
            count = thr_cap_num - new_thr_cap_num;

            if(count <= 0)
                continue;

            //缩容
            pthread_mutex_lock(&pool->thr_mutex);
            pool->thr_cap_num = new_thr_cap_num;
            pthread_mutex_unlock(&pool->thr_mutex);

            //自杀式任务数++++++
            pthread_mutex_lock(&pool->task_mutex);
            pool->task_suicide = count;
            pthread_mutex_unlock(&pool->task_mutex);

            //通知所有线程
            pthread_cond_broadcast(&pool->task_cond);
            continue;
        }
    }

    //销毁所有线程
    pthread_mutex_lock(&pool->thr_mutex);
    thr_cap_num = pool->thr_cap_num;
    thr_len_num = pool->thr_len_num;
    pthread_mutex_unlock(&pool->thr_mutex);

    pthread_mutex_lock(&pool->task_mutex);
    pool->task_suicide = thr_cap_num;
    pthread_mutex_unlock(&pool->task_mutex);

    pthread_cond_broadcast(&pool->task_cond);

    for(i=0;i<thr_max_num;i++){
        if(pool->thr[i] != 0){
            pthread_join(pool->thr[i],NULL);
            pool->thr[i] = 0;
        }
    }

}

threadpool_t* threadpool_create(int thr_min_num,int thr_max_num,int task_cap_num){
    threadpool_t *pool = malloc(sizeof(threadpool_t));
    
    pthread_mutex_init(&pool->thr_mutex,NULL);
    pool->thr = malloc(sizeof(pthread_t) * thr_max_num);
    memset(pool->thr,0,sizeof(pthread_t) * thr_max_num);
    pool->thr_min_num = thr_min_num;
    pool->thr_max_num = thr_max_num;
    pool->thr_cap_num = thr_min_num;
    pool->thr_len_num = 0;
    

    pthread_mutex_init(&pool->task_mutex,NULL);
    pthread_cond_init(&pool->task_cond,NULL);
    pool->task_queue = malloc(sizeof(threadpoll_task_t) * task_cap_num);
    pool->task_cap_num = task_cap_num;
    pool->task_len_num = 0;
    pool->task_head_index = 0;
    pool->task_tail_index = 0;
    pool->task_suicide = 0;

    //创建线程
    int i;
    for(i=0;i<pool->thr_cap_num;i++){
        pthread_create(&pool->thr[i],NULL,threadpool_thread,(void*)pool);
    }

    //管理线程
    pthread_create(&pool->thr_maneger,NULL,threadpoll_admin,(void*)pool);

    return pool;
}

int threadpool_add_task(threadpool_t* pool,void* (*function)(void*),void* arg){
    pthread_mutex_lock(&pool->task_mutex);
    
    while(pool->task_len_num >= pool->task_cap_num)
        pthread_cond_wait(&pool->task_cond,&pool->task_mutex);
    
    //添加任务
    pool->task_queue[pool->task_head_index].function = function;
    pool->task_queue[pool->task_head_index].arg = arg;
    pool->task_head_index = (pool->task_head_index+1) % pool->task_cap_num;
    pool->task_len_num++;
    pthread_mutex_unlock(&pool->task_mutex);

    pthread_cond_signal(&pool->task_cond);
}

void threadpool_destroy(threadpool_t* pool){
    pool->thr_maneger_exit = 1;

    pthread_join(pool->thr_maneger,NULL);

    pthread_mutex_lock(&pool->thr_mutex);
    pthread_mutex_destroy(&pool->thr_mutex);
    pthread_mutex_lock(&pool->task_mutex);
    pthread_mutex_destroy(&pool->task_mutex);
    pthread_cond_destroy(&pool->task_cond);

    free(pool->thr);
    free(pool->task_queue);
    free(pool);
}


void* do_something(void*arg){
    time_t t;
    t = time(NULL);
    printf("-- %lu,%s\n",pthread_self(),ctime(&t));
    sleep(2 * DEFAULT_TIME);
    t = time(NULL);
    printf("!! %lu,%s\n",pthread_self(),ctime(&t));
}

int main(){
    threadpool_t* pool = threadpool_create(20,100,200);


    int i;
    for(i=0;i<1000;i++){
        threadpool_add_task(pool,do_something,NULL);
    }

    sleep(20 * DEFAULT_TIME);
    for(i=0;i<50;i++){
        threadpool_add_task(pool,do_something,NULL);
    }

    sleep(20 * DEFAULT_TIME);
    for(i=0;i<1000;i++){
        threadpool_add_task(pool,do_something,NULL);
    }

    threadpool_destroy(pool);
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值