嵌入式技术笔记(十八):线程池

本文探讨了多线程编程中的问题,如线程数量限制和创建销毁成本,然后介绍了线程池的概念。通过实例展示了如何使用C++实现一个线程池,包括任务队列、任务添加和线程工作。重点在于解决线程池初始化时过度创建的问题,提倡合理设置线程阈值以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 多线程存在的问题
1、进程所支持的线程数量问题(受限)
2、线程的创建和销毁的开销问题

2. 线程池的概念
线程池的概念

3. 创建线程池
要求:创建一个线程池和任务队列, 往任务队列中添加任务,线程池中线程的工作任务是输出"hello world!"、"welcome to China!"和一个传入的参数

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


struct job
{
    void *((*func)(void *arg));
    void *arg;
    struct job *next;
};

struct threadpool
{
    int thread_num; 
    pthread_t *pthread_ids;
    struct job *head; //任务队列的头
    struct job *tail; //任务队列的尾
    int queue_max_num;
    int queue_cur_num;

    pthread_mutex_t mutex;
    pthread_cond_t queue_empty;
    pthread_cond_t queue_not_empty;
    pthread_cond_t queue_not_full;
};

void *threadpool_function(void *arg)
{
    struct threadpool *pool = (struct threadpool *)arg;
    struct job *pjob = NULL;

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

        while(pool->queue_cur_num == 0)
        {
            pthread_cond_wait(&(pool->queue_not_empty), &(pool->mutex));
        }

        pjob = pool->head;
        pool->queue_cur_num--;
        if(pool->queue_cur_num != pool->queue_max_num)
        {
            pthread_cond_broadcast(&(pool->queue_not_empty)); //唤醒条件变量
        }
        if(pool->queue_cur_num == 0)
        {
            pool->head = pool->tail = NULL;
        }
        else
        {
            pool->head = pool->head->next;
        }
        
        pthread_mutex_unlock(&(pool->mutex));
        
        (*(pjob->func))(pjob->arg);
        free(pjob);
        pjob = NULL;
          
    }
}

//线程池初始化函数
struct threadpool *threadpool_init(int thread_num, int queue_max_num)
{
    struct threadpool *pool = (struct threadpool *)malloc(sizeof(struct threadpool));
    //malloc

    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->queue_not_empty), NULL);
    pthread_cond_init(&(pool->queue_not_full), NULL);

    pool->thread_num = thread_num;
    pool->pthread_ids = (pthread_t *)malloc(sizeof(pthread_t) *thread_num);
    //malloc

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

    return pool;
}

//往任务队列里添加任务的函数
void threadpool_add_job(struct threadpool *pool, void *(func)(void *), void *arg) 
{
    pthread_mutex_lock(&(pool->mutex));
    //判断线程池是否为满
    while(pool->queue_cur_num == pool->queue_max_num) 
    {
        pthread_cond_wait((&pool->queue_not_full), &(pool->mutex)); //阻塞等待
    }

    struct job *pjob = (struct job *)malloc(sizeof(struct job));
    //malloc
    //任务队列参数初始化
    pjob->func = func;
    pjob->arg = arg;
    pjob->next = NULL;

    if(NULL == pool->head)
    {
        pool->head = pool->tail = pjob;
        pthread_cond_broadcast(&(pool->queue_not_empty)); 
    }
    else
    {
        pool->tail->next = pjob;
        pool->tail = pjob;
    }
    
    pool->queue_cur_num++;
    printf("%d\n", pool->queue_cur_num);
    pthread_mutex_unlock(&(pool->mutex));
}

void thread_destory(struct threadpool *pool)
{   
    pthread_mutex_lock(&(pool->mutex));
    while(pool->queue_cur_num != 0)
    {
        pthread_cond_wait(&(pool->queue_empty), &(pool->mutex));
    }
    pthread_mutex_unlock(&(pool->mutex));
    pthread_cond_broadcast(&(pool->queue_empty));
    pthread_cond_broadcast(&(pool->queue_not_empty));
    pthread_cond_broadcast(&(pool->queue_not_full));

    free(pool->pthread_ids); //释放存放线程号的空间
    
    for (int i = 0; i < pool->thread_num; i++)
    {
        pthread_cancel(pool->pthread_ids[i]);
        pthread_join(pool->pthread_ids[i], NULL);
    }
    //释放任务队列
    struct job *temp;
    while(pool->head != NULL)
    {
        temp = pool->head;
        pool->head = temp->next;
        free(temp);
    }

    free(pool); //释放线程池
}

//任务的工作函数
void *work(void *arg)
{
    char *p = (char *)arg;
    printf("hello world!  %s\n", p);
    printf("welcome to China!  %s\n", p);
    sleep(1);
}

int main()
{
    struct threadpool *pool = threadpool_init(10, 100); //线程池初始化
    threadpool_add_job(pool, work, "1");
    threadpool_add_job(pool, work, "2");
    threadpool_add_job(pool, work, "3");
    threadpool_add_job(pool, work, "4");
    threadpool_add_job(pool, work, "5");
    threadpool_add_job(pool, work, "6");
    threadpool_add_job(pool, work, "7");
    threadpool_add_job(pool, work, "8");
    threadpool_add_job(pool, work, "9");
    threadpool_add_job(pool, work, "10");

    return 0;
}

运行结果如下:
线程池工作运行截图
创建的线程池存在的问题:
由于不知道有多少线程,所以初始化时容易创建过多的线程,造成资源浪费(解决方案:先设置一个阈值,当超过这个阈值就再创建一些线程;若不超过阈值,就不用再创建线程)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值