线程池

线程池

池化技术:主要用于解决频繁的创建销毁操作带来的大量资源占用,顺带解决内存空间管理的问题

线程池实现思路:
1、需要有一个主线程处理请求
2、需要有一个管理线程处理任务队列和线程池的运行
3、线程池(任务队列空,线程池的线程等待,有任务时通知线程操作)
4、锁和条件变量(线程同步)

使用场景:

  • 高并发、任务执行时间短的业务,线程池线程数可以设置为CPU核数+1,减少线程上下文的切换
  • 并发不高、任务执行时间长的业务要区分开看:
    • 假如是业务时间长集中在IO操作上,也就是IO密集型的任务,因为IO操作并不占用CPU,所以不要让所有的CPU闲下来,可以加大线程池中的线程数目,让CPU处理更多的业务
    • 假如是业务时间长集中在计算操作上,也就是计算密集型任务,这个就没办法了,和(1)一样吧,线程池中的线程数设置得少一些,减少线程上下文的切换
  • 并发高、业务执行时间长,解决这种类型任务的关键不在于线程池而在于整体架构的设计,看看这些业务里面某些数据是否能做缓存是第一步,增加服务器是第二步,至于线程池的设置,设置参考(2)。最后,业务执行时间长的问题,也可能需要分析一下,看看能不能使用中间件对任务进行拆分和解耦

用到的接口:

int pthread_create(pthread_t *thread, 
				   const pthread_attr_t *attr,
                   void *(*start_routine) (void *), 
                   void *arg);

int pthread_join(pthread_t thread, 
				 void **retval);

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
           			   const pthread_mutexattr_t *restrict attr);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_cond_init(pthread_cond_t *restrict cond,
					  const pthread_condattr_t *restrict attr);

int pthread_cond_destroy(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *restrict cond,
					  pthread_mutex_t *restrict mutex);

代码:

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

typedef struct job//任务链结构
{
    void *(*pthread_function)(void *arg);
    void *arg;

    struct job *next;
}job;

typedef struct pthread_pool//线程池结构
{
    pthread_t *pthread_id;
    pthread_t manage_id;

    int pthread_num;
    int pthread_max_num;
    int pthread_min_num;

    job *job_head;
    job *job_tail;

    int job_queue_num;
    int job_queue_max_num;

    pthread_mutex_t mutex;
    pthread_cond_t job_queue_is_not_empty;
    pthread_cond_t job_queue_is_not_full;

}pthread_pool;

//线程初始化后线程执行任务
void *pthread_handle(void *arg)
{
    pthread_pool *pool = (pthread_pool *)arg;

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

        while(pool->job_queue_num == 0)
        {
            pthread_cond_wait(&(pool->job_queue_is_not_empty), &(pool->mutex));
        }

        job *run_job;
        run_job = pool->job_head;
        printf("get function running\n");
        
        pool->job_head = pool->job_head->next;
        pool->job_queue_num--;

        pthread_cond_broadcast(&(pool->job_queue_is_not_full));
        pthread_mutex_unlock(&(pool->mutex));

        pool->pthread_num++;
        run_job->pthread_function(run_job->arg);
        pool->pthread_num--;

        free(run_job);
    }
}

//管理线程执行的任务
void *pthread_pool_manage_handle(void *arg)
{
    pthread_pool *pool = (pthread_pool *)arg;

    while(1)
    {
        int i;
        int count = 0;
        sleep(5);//修改
        pthread_mutex_lock(&(pool->mutex));

        if((pool->job_queue_num > 10) && (pool->pthread_num < pool->pthread_max_num))
        {
            printf("-----------add pthread 5----------\n");
            for(i = 0; (count < 5) && (pool->pthread_num < pool->pthread_max_num); i++)
            {
                if(pool->pthread_id[i] == 0)
                {
                    pthread_create(&(pool->pthread_id[i]), NULL, pthread_handle, (void *)pool);
                    count++;
                    pool->pthread_min_num++;
                }
            }
        }
        printf("pthread_num = %d\n", pool->pthread_num);//测试
        printf("pthread_min_num = %d\n", pool->pthread_num);
        printf("job_queue_num = %d\n", pool->job_queue_num);
        if((pool->pthread_num < 2) && (pool->pthread_min_num >= 2) && (pool->job_queue_num < 2))
        {
            printf("-------------sub pthread---------------");
            pool->pthread_min_num = 2;
            for(i = pool->pthread_max_num; i >= pool->pthread_max_num; i--)
            {
                pthread_join(pool->pthread_id[i], NULL);
            }
        }

        pthread_mutex_unlock(&(pool->mutex));
    }
}

int pthread_pool_add_job(pthread_pool *pool, void *(*function)(void *), void *arg)
{
    pthread_mutex_lock(&(pool->mutex));//先上锁

    while(pool->job_queue_num == pool->job_queue_max_num)
    {
        printf("job queue is full\n");
        pthread_cond_wait(&(pool->job_queue_is_not_full), &(pool->mutex));
    }

    job *new_job = (job *)malloc(sizeof(job));
    new_job->pthread_function = function;
    new_job->arg = arg;
    new_job->next = NULL;

    if(pool->job_head == NULL)
    {
        pool->job_head = new_job;
        pool->job_tail = new_job;
    }
    else
    {
        pool->job_tail->next = new_job;
        pool->job_tail = pool->job_tail->next;
    }

    pool->job_queue_num++;

    pthread_cond_broadcast(&(pool->job_queue_is_not_empty));

    pthread_mutex_unlock(&(pool->mutex));//解锁

    return 0;
}

//线程池初始化
pthread_pool *pthread_pool_init(int pthread_min_num, int pthread_max_num, int job_queue_max_num)
{
    pthread_pool *pool;

    pool = (pthread_pool *)malloc(sizeof(pthread_pool));

    pool->pthread_min_num = pthread_min_num;
    pool->pthread_max_num = pthread_max_num;
    pool->pthread_id = (pthread_t *)malloc(sizeof(pthread_t) * pthread_max_num);

    memset(pool->pthread_id, 0, sizeof(pthread_t) * pthread_max_num);

    pool->job_head = NULL;
    pool->job_tail = NULL;
    pool->job_queue_num = 0;
    pool->job_queue_max_num = job_queue_max_num;

    if(pthread_mutex_init(&(pool->mutex), NULL) < 0)
    {
        printf("init mutex error\n");
        exit(1);
    }

    if(pthread_cond_init(&(pool->job_queue_is_not_empty), NULL) < 0)
    {
        printf("init is not empty error\n");
        exit(1);
    }

    if (pthread_cond_init(&(pool->job_queue_is_not_full), NULL) < 0)
    {
        printf("init is not full error\n");
        exit(1);
    }

    for(int i = 0; i < pool->pthread_min_num; i++)
    {
        pthread_create(&(pool->pthread_id[i]), NULL, pthread_handle, (void *)pool);
    }

    pthread_create(&(pool->manage_id), NULL, pthread_pool_manage_handle, (void *)pool);

    return pool;
}

int pthread_pool_destory(pthread_pool *pool)
{
    int i;
    for(i = 0; i < pool->pthread_num; i++)
    {
        printf("i = %d\n", i);
        pthread_join(pool->pthread_id[i], NULL);
    }

    pthread_mutex_destroy(&(pool->mutex));
    pthread_cond_destroy(&(pool->job_queue_is_not_full));
    pthread_cond_destroy(&(pool->job_queue_is_not_empty));

    printf("free pool\n");
    free(pool->pthread_id);
    free(pool);
    
    return 0;
}

void *func(void *arg)
{
    printf("thread func data = %s\n", (char *)arg);
    sleep(4);//修改
}

int main()
{
    pthread_pool *pool = pthread_pool_init(2, 100, 50);

    pthread_pool_add_job(pool,func,"1");
    pthread_pool_add_job(pool,func,"2");
    pthread_pool_add_job(pool,func,"3");
    pthread_pool_add_job(pool,func,"4");

    pthread_pool_add_job(pool,func,"5");


    pthread_pool_add_job(pool,func,"6");
    pthread_pool_add_job(pool,func,"7");
    pthread_pool_add_job(pool,func,"8");
    pthread_pool_add_job(pool,func,"9");


    pthread_pool_add_job(pool,func,"10");
    pthread_pool_add_job(pool,func,"11");
    pthread_pool_add_job(pool,func,"12");
    pthread_pool_add_job(pool,func,"13");


    pthread_pool_add_job(pool,func,"14");
    pthread_pool_add_job(pool,func,"15");
    pthread_pool_add_job(pool,func,"16");
    pthread_pool_add_job(pool,func,"17");

    pthread_pool_add_job(pool,func,"18");
    pthread_pool_add_job(pool,func,"19");
    pthread_pool_add_job(pool,func,"20");
    pthread_pool_add_job(pool,func,"21");


    pthread_pool_add_job(pool,func,"22");
    pthread_pool_add_job(pool,func,"23");
    pthread_pool_add_job(pool,func,"24");
    pthread_pool_add_job(pool,func,"25");

    pthread_pool_add_job(pool,func,"26");
    pthread_pool_add_job(pool,func,"27");
    pthread_pool_add_job(pool,func,"28");
    pthread_pool_add_job(pool,func,"29");
    pthread_pool_add_job(pool,func,"30");

    sleep(1000);

    pthread_pool_destory(pool);


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值