线程池技术

目录

一、线程池概述

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

2、线程池的核心

二、线程池的实现

1、线程池实现的一般步骤:

(1)完成任务队列结构体、线程池结构体

(2)初始化线程池:将线程池内部变量注意初始化;

(3)写线程函数(固定格式):先加互斥锁;将任务队列中任务取出执行;没有任务,就等待队列不为空;取出任务后,执行任务函数;队列头指针加1,任务数减1;然后解锁;

(4)写任务进队列函数(重点):先加互斥锁;等待队列不满(链式队列不存在);将任务放入人户队列中(任务包含:任务函数、函数参数);队列尾指针加1,任务数加1;然后解锁;

(5)写任务函数功能(重点:可以调用功能不同的函数):任务函数可以功能各不相同(函数名不同),但是参数与结构必须相同;

(6)销毁线程池(固定格式):等待队列为空;唤醒所以线程;释放所有线程;销毁互斥锁和条件变量;将队列置空;释放pool;

2、代码实现

三、可伸缩线程池的实现


一、线程池概述

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

一个进程所支持的线程是有限的(受限);

线程的创建与销毁是有一定的开销的(当线程数目多时);

(内存池是解决频繁malloc产生的开销问题;对象池是解决对象频繁分配所带来的开销问题)

2、线程池的核心

任务队列:用来存放客户端所请求的服务(所要完成的功能函数)

线程池:用于存放线程(还包含线程数量,任务队列头/尾指针,任务队列大小,互斥锁,条件变量,线程销毁标志位等)

当任务队列为空时,线程池里的线程阻塞等待;

任务队列不为空时,线程池里的线程处理任务;

任务队列为满时,不能再次新增任务;

二、线程池的实现

1、线程池实现的一般步骤:

(1)完成任务队列结构体、线程池结构体

最完整版:

struct job{
    void *(*func)(void *arg);    //队列中的函数
    void *arg;                  //功能函数的参数
    struct job *next;             // 指向下一个节点
};

struct threadpool{
    int thread_num;             //线程的个数
    pthread_t *ids;              //线程的id

    int queue_max_num;           //队列的最大容量
    int queue_cur_num;          //队列正在执行的个数
    struct job *head;           //队列的头
    struct job *tail;           //队列的尾

    pthread_mutex_t mutex;       //锁队列的增与减
    pthread_cond_t not_empty;     //非空
    pthread_cond_t not_full;       //非满
    pthread_cond_t queue_empty;   //队列为空

    
};

注意:队列函数可以按要求更改;线程池结构体(队列非满(not_full)可以省略(链式队列无满情况),队列为空(queue_empty)也可以去掉,队列最大容量(queue_max_num)也可以去掉,链式队列无最大容量)也可更改;

(2)初始化线程池:将线程池内部变量注意初始化;

(3)写线程函数(固定格式):先加互斥锁;将任务队列中任务取出执行;没有任务,就等待队列不为空;取出任务后,执行任务函数;队列头指针加1,任务数减1;然后解锁

(4)写任务进队列函数(重点):先加互斥锁;等待队列不满(链式队列不存在);将任务放入人户队列中(任务包含:任务函数、函数参数);队列尾指针加1,任务数加1;然后解锁;

(5)写任务函数功能(重点:可以调用功能不同的函数):任务函数可以功能各不相同(函数名不同),但是参数与结构必须相同;

(6)销毁线程池(固定格式):等待队列为空;唤醒所以线程;释放所有线程;销毁互斥锁和条件变量;将队列置空;释放pool;

2、代码实现

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

struct job{
    void *(*func)(void *arg);    //队列中的函数
    void *arg;                  //功能函数的参数
    struct job *next;             // 指向下一个节点
};

struct threadpool{
    int thread_num;             //线程的个数
    pthread_t *ids;              //线程的id

    int queue_max_num;           //队列的最大容量
    int queue_cur_num;          //队列正在执行的个数
    struct job *head;           //队列的头
    struct job *tail;           //队列的尾

    pthread_mutex_t mutex;       //锁队列的增与减
    pthread_cond_t not_empty;     //非空
    pthread_cond_t not_full;       //非满
    pthread_cond_t queue_empty;   //队列为空

    
};

void *thread_function(void *arg)   //线程函数
{
    struct threadpool *pool = (struct threadpool *)arg;
    struct job *fjob = NULL;

    while (1)
    {
        pthread_mutex_lock(&(pool->mutex));
        if (pool->queue_cur_num == 0)
        {
            pthread_cond_wait(&(pool->not_empty), &(pool->mutex));
        }

        fjob = pool->head;
        pool->queue_cur_num--;

        if (pool->queue_cur_num != pool->queue_max_num)
        {
            pthread_cond_signal(&(pool->not_full));
        }
        

        if (pool->queue_cur_num == 0)
        {
            pool->head = pool->tail = NULL;
            pthread_cond_signal(&(pool->queue_empty));
        }
        else
        {
            pool->head = pool->head->next;
        }

        pthread_mutex_unlock(&(pool->mutex));

        (*(fjob->func))(fjob->arg);
        free(fjob);
        fjob = NULL;
        
    }
    
}

struct threadpool *threadpool_init(int thread_num, int queue_max_num)   //初始化线程池
{

    struct threadpool *pool = (struct threadpool *)malloc(sizeof(struct threadpool));

    pool->thread_num = thread_num;
    pool->ids = (pthread_t *)malloc(sizeof(pthread_t)*thread_num);
    pool->queue_max_num = queue_max_num;
    pool->queue_cur_num = 0;
    pool->head = NULL;
    pool->tail = NULL;

    pthread_mutex_init(&(pool->mutex), NULL);
    pthread_cond_init(&(pool->queue_empty), NULL);
    pthread_cond_init(&(pool->not_empty), NULL);
    pthread_cond_init(&(pool->not_full), NULL);

    for (int i = 0; i < pool->thread_num; i++)
    {
        pthread_create(&(pool->ids[i]), NULL, (void *)thread_function, (void *)pool);
    }
    
    return pool;
}

void *work_function(void *arg)   //队列函数
{
    char *p = (char *)arg;
    printf("hello word!%s\n", p);
    printf("welcome jestc!%s\n", p);
    sleep(1);
}

void threadpool_add_job(struct threadpool *pool, void *(*work_function)(void *), void *arg)   //向队列中添加任务节点
{
    pthread_mutex_lock(&(pool->mutex));
    while (pool->queue_cur_num == pool->queue_max_num)
    {
        pthread_cond_wait(&(pool->not_full), &(pool->mutex));
    }

    struct job * fjob = (struct job *)malloc(sizeof(struct job));
    fjob->next = NULL;
    fjob->func = work_function;
    fjob->arg = arg;

    if (pool->head == NULL)
    {
        pool->head = pool->tail = fjob;
        pthread_cond_signal(&(pool->not_empty));
    }
    else
    {
        pool->tail->next = fjob;
        pool->tail = fjob;
    }

    pool->queue_cur_num++;

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

void  threadpool_destory(struct threadpool *pool)    //释放线程池
{
    pthread_mutex_lock(&(pool->mutex));

    while (1)
    {
        pthread_cond_wait(&(pool->queue_empty), &(pool->mutex));
    }

    pthread_mutex_unlock(&(pool->mutex));

    pthread_cond_signal(&(pool->not_empty));   //唤醒线程池
    pthread_cond_signal(&(pool->not_full));

    for (int  i = 0; i < pool->thread_num; i++)
    {
        pthread_join(pool->ids[i], NULL);
    }
    
    pthread_mutex_destroy(&(pool->mutex));
    pthread_cond_destroy(&(pool->not_empty));
    pthread_cond_destroy(&(pool->not_full));
    pthread_cond_destroy(&(pool->queue_empty));

    free(pool->ids);

    struct job *temp = NULL;
    while (pool->head != NULL)
    {
        temp = pool->head;
        pool->head = temp->next;
        free(temp);
    }

    free(pool);
    
}


int main(int argc, char *argv[])
{
    struct threadpool * pool = threadpool_init(5, 100);    //创建线程池

    threadpool_add_job(pool, (void *)work_function, "1");   //向队列中添加任务节点
    threadpool_add_job(pool, (void *)work_function, "2");
    threadpool_add_job(pool, (void *)work_function, "3");
    threadpool_add_job(pool, (void *)work_function, "4");
    threadpool_add_job(pool, (void *)work_function, "5");
    threadpool_add_job(pool, (void *)work_function, "6");
    threadpool_add_job(pool, (void *)work_function, "7");
    threadpool_add_job(pool, (void *)work_function, "8");
    threadpool_add_job(pool, (void *)work_function, "9");
    threadpool_add_job(pool, (void *)work_function, "10");

    threadpool_add_job(pool, (void *)work_function, "11");   //向队列中添加任务节点
    threadpool_add_job(pool, (void *)work_function, "12");
    threadpool_add_job(pool, (void *)work_function, "13");
    threadpool_add_job(pool, (void *)work_function, "14");
    threadpool_add_job(pool, (void *)work_function, "15");
    threadpool_add_job(pool, (void *)work_function, "16");
    threadpool_add_job(pool, (void *)work_function, "17");
    threadpool_add_job(pool, (void *)work_function, "18");
    threadpool_add_job(pool, (void *)work_function, "19");
    threadpool_add_job(pool, (void *)work_function, "20");

    threadpool_destory(pool);

    return 0;
}

注意:任务函数金队列和任务函数尤为重要;

三、可伸缩线程池的实现

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值