CPP服务器05--线程池实现(1)

线程池封装 1

实现思路:
  1. 组件:

    • pthread_t *workers; //工作线程数组
    • pthread_t manager; //管理者线程
    • TaskQueue *task_queue; //任务队列
  2. 思路:

    1. 多个工作线程,外部线程添加任务,结合阻塞任务队列实现生产消费者模型;
    2. 管理者线程负责工作线程的调度策略
      1. 比如说,存活数小于设定最大线程数且存在未执行任务,则创建线程
      2. 当忙碌线程小于当前存活线程数且,则进行线程销毁.
实现: 任务和任务队列
#ifndef TASK_HPP
#define TASK_HPP


#include <pthread.h>
#include <queue>

using callback = void(*)(void*);

struct Task
{
    Task()
    {
        function = nullptr;
        arg = nullptr;
    }

    Task(callback f, void *arg)
    {
        function = f;
        this->arg = arg;
    }

    callback function;
    void *arg;

};



class TaskQueue
{
public:
    TaskQueue()
    {
        pthread_mutex_init(&__mutex__, NULL);
    }

    ~TaskQueue()
    {
        pthread_mutex_destroy(&__mutex__);
    }

    void add_task(Task &task)
    {
        pthread_mutex_lock(&__mutex__);
        __queue__.push(task);
        pthread_mutex_unlock(&__mutex__);
    }

    void add_task(callback func, void *arg)
    {
        Task task(func, arg);
        add_task(task);
    }


    Task take_task()
    {
        Task task;
        pthread_mutex_lock(&__mutex__);
        if(__queue__.size() > 0)
        {
            task = __queue__.front();
            __queue__.pop();
        }
        pthread_mutex_unlock(&__mutex__);
        return task;
    }

    inline int get_task_number()
    {
        return __queue__.size();
    }

private:
    pthread_mutex_t __mutex__;
    std::queue<Task> __queue__;
};

#endif
实现:线程池
#include "task.hpp"
#include "../log/log.h"

#include <pthread.h>
#include <string.h>
#include <iostream>
#include <string>
#include <unistd.h>

class ThreadPool
{
public:
    ThreadPool(int min, int max);
    ~ThreadPool();
    void add_task(Task &task);   //添加任务
    int get_busy_number();       //获取忙碌线程数
    int get_alive_number();      //获取存活线程数

private:
    static void *worker(void *arg); //工作线程函数
    static void *manager(void*arg); //管理者线程调度逻辑
    void thread_exit();             //退出指定工作线程
    static const int __NUMBER__ = 2;//每次新建线程数上限制

private:
    pthread_mutex_t __lock__;    //队列访问互斥锁
    pthread_cond_t __notEmpty__; //生产消费者模型条件变量
    pthread_t *__workers__;      //工作线程数组
    pthread_t __manager__;       //管理者线程
    TaskQueue *__task_queue__;   //任务队列
    int __minNum__;              //最小线程数
    int __maxNum__;              //最大线程数
    int __busyNum__;             //忙碌线程数
    int __aliveNum__;            //存活线程数
    int __exitNum__;             //待退出线程数
    bool __shutdown__ = false;   //关闭池子标志位置

};


ThreadPool::ThreadPool(int min, int max)
{
    __task_queue__ = new TaskQueue;
    do
    {
        __minNum__ = min;
        __maxNum__ = max;
        __busyNum__ = 0;
        __aliveNum__ = 0;

        __workers__ = new pthread_t[max];
        memset(__workers__, 0, sizeof(pthread_t)*max);

        if (pthread_mutex_init(&__lock__, nullptr)!=0||
            pthread_cond_init(&__notEmpty__,nullptr)!=0)
        {
            // printf("THREADPOOL: init mutex or condition fail...");
            break;
        }

        for(int i=0; i<min; ++i)
        {
            pthread_create(&__workers__[i],nullptr,worker,this);
        }

        pthread_create(&__manager__, nullptr, manager, this);
    } while (0);
}


ThreadPool::~ThreadPool()
{
    __shutdown__ = 1;
    pthread_join(__manager__, nullptr);
    for(int i=0; i<__aliveNum__; ++i)
    {
        pthread_cond_signal(&__notEmpty__);
    }

    if(__task_queue__) delete __task_queue__;
    if(__workers__) delete __workers__;
    pthread_mutex_destroy(&__lock__);
    pthread_cond_destroy(&__notEmpty__);
}


void ThreadPool::add_task(Task &task)
{
    if (__shutdown__) return;

    __task_queue__->add_task(task);
    pthread_cond_signal(&__notEmpty__);
}


int ThreadPool::get_busy_number()
{
    int tmp = 0;
    pthread_mutex_lock(&__lock__);
    tmp = __busyNum__;
    pthread_mutex_unlock(&__lock__);
    return tmp;
}


int ThreadPool::get_alive_number()
{
    int tmp = 0;
    pthread_mutex_lock(&__lock__);
    tmp = __aliveNum__;
    pthread_mutex_unlock(&__lock__);
    return tmp;
}


void* ThreadPool::worker(void* arg)
{
    ThreadPool *pool = static_cast<ThreadPool*>(arg);
    while (true)
    {
        pthread_mutex_lock(&pool->__lock__);
        while (pool->__task_queue__->get_task_number()==0 && !pool->__shutdown__)
        {
            // printf("THREADPOOL: Thread %ld is waiting.", pthread_self());
            pthread_cond_wait(&pool->__notEmpty__, &pool->__lock__);
            if(pool->__exitNum__>0)
            {
                pool->__exitNum__--;
                if(pool->__aliveNum__ > pool->__minNum__)
                {
                    pool->__aliveNum__--;
                    pthread_mutex_unlock(&pool->__lock__);
                    pool->thread_exit();
                }
            }
        }

        if(pool->__shutdown__)
        {
            pthread_mutex_unlock(&pool->__lock__);
            pool->thread_exit();
        }

        Task task = pool->__task_queue__->take_task();
        pool->__busyNum__++;
        pthread_mutex_unlock(&pool->__lock__);
        // printf("THREADPOOL: Thread %ld start working....", pthread_self());
        task.function(task.arg);

        // delete task.arg;
        task.arg = nullptr;
        // printf("THREADPOOL: Thread %ld end working...", pthread_self());
        pthread_mutex_lock(&pool->__lock__);
        pool->__busyNum__--;
        pthread_mutex_unlock(&pool->__lock__);
    }
}


void* ThreadPool::manager(void*arg)
{
    ThreadPool *pool = static_cast<ThreadPool*>(arg);
    while (!pool->__shutdown__)
    {
        sleep(3);

        pthread_mutex_lock(&pool->__lock__);
        int queueSize = pool->__task_queue__->get_task_number();
        int liveNum = pool->__aliveNum__;
        int busyNum = pool->__busyNum__;
        pthread_mutex_unlock(&pool->__lock__);

        if (queueSize > liveNum && liveNum < pool->__maxNum__)
        {
            pthread_mutex_lock(&pool->__lock__);
            int counter = 0;
            for(int i=0; i < pool->__maxNum__ && counter < __NUMBER__; ++i)
            {
                if(pool->__workers__[i] == 0)
                {
                    pthread_create(&pool->__workers__[i], nullptr, worker,pool);
                    counter++;
                    pool->__aliveNum__++;
                }
            }
            pthread_mutex_unlock(&pool->__lock__);
        }

        if(busyNum*2<liveNum && liveNum>pool->__minNum__)
        {
            pthread_mutex_lock(&pool->__lock__);
            pool->__exitNum__ = __NUMBER__;
            pthread_mutex_unlock(&pool->__lock__);

            for(int i=0; i<__NUMBER__; i++)
            {
                pthread_cond_signal(&pool->__notEmpty__);
            }
        }
    }
    return nullptr;
}


void ThreadPool::thread_exit()
{
    pthread_t tid = pthread_self();
    for (int i = 0; i < __maxNum__; ++i)
    {
        if (__workers__[i] == tid)
        {
            __workers__[i] = 0;
            
            // printf("THREADPOOL: thread %ld is exitiong...", pthread_self());
            break;
        }
    }
    pthread_exit(NULL);
}
测试代码
#include "../threadpool/task.hpp"
#include "../threadpool/threadpool.hpp"
#include <stdlib.h>
#include <stdio.h>

void task_func(void *arg)
{
    int num = *(int*)arg;
    printf("thread %ld is working, num=%d\n",pthread_self(),num);
    sleep(1);
}

int main(int argc, char const *argv[])
{
    ThreadPool pool(1,5);
    for(int i=0; i<100; ++i)
    {
        int *num = (int*)malloc(sizeof(int));
        *num = i+100;
        Task task(task_func, num);
        pool.add_task(task);
    }

    sleep(30);
    return 0;
}
引用
  1. https://subingwen.cn/linux/threadpool-cpp/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ColaForced

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值