linux-线程池实现

线程池-pthread_pool

  1. 含义:顾名思义,线程池是集中管理多个线程的工具,在其中包含着多个线程的存储以及对线程任务的处理。
  2. 源代码:

1)任务序列:
通过回调函数call_back指定线程所要执行的任务。
在线程池中用struct job*head,tail链接形成任务序列。

struct jobs{
    void* (*call_back)(void* i);
    void* i;
    struct jobs* next; 
};

2)线程池结构体:

struct thread_pool
{
    int pthread_num;//线程数目
    int queue_max_num;//任务队列的最大数目
    int queue_cur_num;//任务队列的当前数目
    struct jobs* head;//任务队列头指针
    struct jobs* tail;//任务队列尾指针
    pthread_t *pthreads;//线程数组
    pthread_mutex_t mutex;
    pthread_cond_t queue_empty;//队列为空
    pthread_cond_t queue_not_empty;//队列不为空(任务队列有任务)
    pthread_cond_t queue_not_full;//队列不为满
    int pool_close;

};

3)线程池初始化函数
返回一个空的线程池指针new

struct thread_pool* pool_init(int pthread_num,int queue_max_num)
{
    struct thread_pool *new=(struct thread_pool*)malloc(sizeof(struct thread_pool));
    new->pthread_num=pthread_num;
    new->queue_max_num=queue_max_num;
    new->queue_cur_num=0;
    new->head=new->tail=NULL;
    new->pthreads=malloc(sizeof(pthread_t)*pthread_num);

    for(int i=0;i<pthread_num;i++)
    {
       pthread_create(&new->pthreads[i],NULL,pool_function,(void*)new);
       // 每个线程默认执行pool_function函数 并将线程池传入
    }
    pthread_mutex_init(&new->mutex,NULL);
    pthread_cond_init(&new->queue_empty,NULL);
    pthread_cond_init(&new->queue_not_empty,NULL);
    pthread_cond_init(&new->queue_not_full,NULL);
    new->pool_close=0;
    if(new==NULL){
        printf("init erro\n");
        return 0;
    }
    else return new;
}

4)添加任务函数函数
向线程池任务队列中添加任务,function为函数指针即线程要执行的函数。

void add_job(struct thread_pool* pool,void*(*function)(void*),void* i)
{
    
    pthread_mutex_lock(&pool->mutex);
    //如果超过最大值则阻塞中not_full条件上
    while (pool->queue_cur_num==pool->queue_max_num)
    {
        pthread_cond_wait(&pool->queue_not_full,&pool->mutex);
    }
    
    //初始化job
    struct jobs* job=malloc(sizeof(struct jobs));
    if(job==NULL){
        printf("job malloc erro");
        _exit(0);
    }
    job->call_back=function;
    job->i=i;
    //将job添加到pool中的链表
    if(pool->head==NULL&&pool->tail==NULL)//如果job为第一个
    {
        job->next=NULL;
        pool->head=pool->tail=job;
    }
    else{
        pool->tail->next=job;
        pool->tail=job;
    }
    pool->queue_cur_num++;
    pthread_mutex_unlock(&pool->mutex);
    if(pool->queue_cur_num!=0) 
        pthread_cond_signal(&pool->queue_not_empty);

} 

5)loop:每个线程循环执行的函数
//不断的执行任务队列中的任务

void* pool_function(void* i)
{
    struct thread_pool* pool=(struct thread_pool*)i;
    
    while(1){
    pthread_mutex_lock(&pool->mutex);
    while(pool->queue_cur_num==0&&pool->pool_close==0)
    {
        pthread_cond_wait(&pool->queue_not_empty,&pool->mutex);//刚创建所有的线程都会阻塞在not_empty这个条件上
    }
    //当等待队列不为空时,执行其中的一个job
 
    struct jobs *pjob=pool->head;
    pool->queue_cur_num--;
    //执行完一个程序后唤醒阻塞中not_full上的线程
    if(pool->queue_cur_num<pool->queue_max_num)
        pthread_cond_signal(&pool->queue_not_full);
    pool->head=pool->head->next;
    //到最后head会为nuLL而tail为最后一个job
    if(pool->head==NULL)
        pool->tail=NULL;
    pthread_mutex_unlock(&pool->mutex);

    (*(pjob->call_back))(pjob->i);//执行第一个job的函数  
     free(pjob);
     if(pool->queue_cur_num==0&&pool->pool_close==0)
        pthread_cond_signal(&pool->queue_empty);
  }
}

6)供测试用的任务函数

void* work(void* i)
{
    printf("i do it\n");
}
void* print1(void* i)
{
    printf("1\n");
}

7)线程池销毁
释放内存,销毁锁

void destroy(struct thread_pool* pool)
{
    pthread_mutex_lock(&pool->mutex);
    if(pool->queue_cur_num!=0)
        pthread_cond_wait(&pool->queue_empty,&pool->mutex);
    struct jobs* temp;
    // struct jobs* cur=pool->head;
    while(pool->head!=pool->tail)
    {
        temp=pool->head;
        pool->head=pool->head->next;
        free(temp);
    }

    free(pool->head);
    free(pool->tail);
    for(int i=0;i<pool->pthread_num;i++)
    {
    pthread_join(pool->pthreads[i],NULL);
    }
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->queue_empty);
    pthread_cond_destroy(&pool->queue_not_empty);
    pool->pool_close=1;//关闭标志
}

8)main函数

int main()
{
    struct thread_pool *pool=pool_init(5,10);//5个线程 10个job
    add_job(pool,work,NULL);
    add_job(pool,work,NULL);
    add_job(pool,print1,NULL);
    add_job(pool,print1,NULL);
    add_job(pool,print1,NULL);
    add_job(pool,print1,NULL);
    add_job(pool,print1,NULL);
    sleep(4);
    destroy(pool);
    while(1);

    return 0;
}

3.执行结果:
与所预想结果对应,调用了2次work函数,5次print1函数,因为只有5个线程,所以应该是成功了.
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值