004.池式结构之线程池

目录

1、线程池的基本思想

2、线程池的进阶想法

3、基本框架实现代码

4、 开源组件使用的线程池


1、线程池的基本思想

(1)减少线程的创建和销毁带来的内存的消耗。

(2)可以将主线程与其他无关工作任务异步解耦,由线程池去完成主线程无关的工作,如 记录日志的任务就可以抛入线程池去执行。也可以异步处理耗时的操作

(3)线程池的基本思想,来源于 工作者 和 任务。  工作者不断从任务队列取任务执行,主线程则不断往工作队列中加入新的执行任务。

2、线程池的进阶想法

(1)可以创建多个线程池,不同线程池执行不同类别的任务,或者可以通过多个线程池,完成对任务优先级的划分。

(2)对于 计算密集型(CPU经常参与的) 以及 任务密集型(重IO操作的,经常等待的),线程池可以创建不同数量的线程个数。

(3)可以根据 执行任务加减计数,以及当前线程数,计算个任务增长比例的水线,动态增加或者回收线程池使用的线程个数。

3、基本框架实现代码

代码大体框架如下:

(1)实现两个对象 生产者(NJOB) 和 消费者(NWORKER) 

(2)线程池 由 消费者组成的线程队列,以及生产者组成的任务等待队列。

(3)线程池主要由三个函数  

thread_pool_create 创建线程池,并创建每个线程的回调函数

thread_pool_destory 销毁线程池

thread_pool_pushjob 将任务不断放入线程池的任务等待队列中

(4)线程池中每个线程的工作过程  thread_callback

从等待队列中取任务 。 gettask

执行该任务。                exectask

(5)任务由主线程抛入,提供对应的执行函数以及入参 。

//头插法
#define LL_ADD(item, list) do{              \
    item->prev = NULL;                      \
    item->next = list;                      \
    if (list != NULL) list->prev = next;    \
    list = item;                            \
}while (0)

#define LL_REMOVE(item, list) do{                           \
    if(item->prev != NULL) item->prev->next = item->next;   \
    if(item->next != NULL) item->next->prev = item->prev;   \
    if (item == list) list = item->next;                    \
    item->prev = NULL;                                      \
    item->next = NULL;                                      \
}while (0)


struct NWORKER
{
    pthread_t id;
    int terminate;

    nthreadpool* pool;

    struct NWORKER* prev;
    struct NWORKER* next;
}nworker;

struct NJOB
{
    void (*job_func)(void* arg);
    void* usr_data;

    struct NJOB* prev;
    struct NJOB* next;
}njob;

struct NTHREADPOOL
{
    struct NWORKER* workers;
    struct NJOB* wait_jobs;

    pthread_cond_t cond;    //条件变量
    pthread_mutex_t mtx;
}nthreadpool;

void* thread_callback(void* arg)
{
    nworker* worker = (nworker*)arg;

    while (1)
    {
        //get job 
        phtread_mutex_lock(&worker->pool->mtx);
        while (worker->pool->wait_jobs != NULL)
        {
            if (worker->terminate == 1)
            {
                break;
            }
            phtread_cond_wait(&worker->pool->cond, &worker->pool->mtx);
        }

        if (worker->terminate == 1)
        {
            phtread_mutex_unlock(&worker->pool->mtx);
            break;
        }

        njob *job = worker->pool->wait_jobs;
        if (job)
        {
            LL_REMOVE(job, worker->pool->wait_jobs);
        }

        phtread_mutex_unlock(&worker->pool->mtx);

        if (job == NULL)
        {
            continue;
        }

        //exc
        job->job_func(job->usr_data);
    }

    free(worker);
}

int thread_pool_create(nthreadpool* pool, int num_thread)
{
    if (pool == NULL) return -1;

    if (num_thread < 1) num_thread = 1;
    memset(pool, 0, sizeof(nthreadpool));

    pthread_cond_t blank_cond = PTHREAD_COND_INITIALIZER;
    memcpy(&pool->cond, &blank_cond, sizeof(pthread_cond_t));

    pthread_mutex_t blank_mtx = PTHREAD_MUTEX_INITIALIZER;
    memcpy(&pool->mtx, &blank_mtx, sizeof(pthread_mutex_t));

    int idx = 0;
    for (idx = 0; idx < num_thread; ++idx)
    {
        nworker* worker = (nworker*)malloc(sizeof(nworker));
        if (worker == NULL)
        {
            perror("malloc");
            return idx;
        }
        memset(worker, 0, sizeof(nworker));
        worker->pool = pool;

        int ret = pthread_create(&worker->id, NULL, thread_callback, worker);
        if (ret)
        {
            perror("pthread_create");
            free(worker);
            return idx;
        }
        
        LL_ADD(worker, pool->workers);
    }

    return idx;
}

int thread_pool_destory(nthreadpool* pool)
{
    nworker* worker = NULL;
    for (worker = pool->workers; worker != NULL; worker = worker->next)
    {
        worker->terminate = 1;
    }

    pthread_mutex_lock(&pool->mtx);
    pthread_cond_broadcast(&pool->cond);
    pthread_mutex_unlock(&pool->mtx);
}

int thread_pool_pushjob(nthreadpool* pool, njob* job)
{
    pthread_mutex_lock(pool->mtx);

    LL_ADD(job, pool->wait_jobs);
    pthread_cond_signal(&pool->cond);

    pthread_mutex_unlock(pool->mtx);
}

int main()
{
    auto counter = [](njob* job)->void
    {
        if (job == NULL)
        {
            return;
        }

        int idx = *(int*)job->usr_data;
        printf("idx : %d  selfid:%u \n", idx, pthread_self());

        free(job->usr_data);
        free(job);
    }
    nthreadpool pool = { 0 };
    int num_thread = 50;

    thread_pool_create(pool, num_thread);

    for (int i = 0; i < num_thread; ++i)
    {
        njob* job = (njob*)malloc(sizeof(njob));

        job->job_func = counter;
        job->usr_data = malloc(sizeof(int));
        *(int*)job->usr_data = i;

        thread_pool_pushjob(&pool, job);
    }

    return 0;
}

4、 开源组件使用的线程池

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值