手写一个C++线程池-V1

        首先介绍下线程池的作用,线程池属于一种多线程的使用模式,在运行时,生产者会将任务添加到任务队列中,而消费者会在创建线程后从此任务队列中获取任务来自动处理。这样避免了在短时间内创建和销毁线程的代价。线程池不仅能够内核的充分利用,还能防止过分调度。可用的线程数据取决于可用的并发处理器,处理内核,内存,网络sockets等数量。

        线程池中的所有线程都有默认的堆栈大小和默认优先级运行。如果一个线程处于空闲态,例如等待某个事件的发生,那么线程池将会插入另一个线程来使所有的处理器保持繁忙。如果所有的线程始终保持繁忙,但队列中仍有未处理的任务,那么线程池将会在一段时间后创建额外的一个线程(但不会超过线程最大数量)来继续处理任务,如果超过了线程最大数量,那么线程要排队,等待处理任务的线程完成之后才能启动。

        线程池的组成分为3个主要的部分:

        manager线程:数量1个

        (1)周期性检查任务队列的任务数以及处于繁忙状态的工作线程的数量;

        (2)当任务过多时,可以根据策略适当增加一些新的工作线程;

        (3)当任务过少时,可以根据策略释放销毁一些工作线程

        worker线程:数量N个    

        (1)线程池创建维护一定数量的工作线程,这些工作线程会不断的读取任务队列,从队列里取出任务并处理;

        (2)如果任务队列为空,工作线程将会被阻塞;

        (3)如果阻塞之后有了新的任务,由生产者将阻塞解除,工作线程开始工作;

        任务队列:由生产者推送,任务队列存储要处理的任务,工作线程来取并处理这些任务

        (1)线程池提供API,将任务添加到任务队列,或者从任务队列中移除;

        (2)已处理的任务将被移除;

        (3)生产者调用线程池API往任务队列中添加任务。

1.任务队列

任务和任务队列声明:

#pragma once
#include<iostream>
#include<deque>
#include<thread>
#include<mutex>
#include<chrono>

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

template<typename T>
struct Task{
    Task():function(nullptr),arg(nullptr){}

    Task(callback func,void* argument):function(func),arg(argument){}

    callback function;
    T* arg;
};

template<typename T>
class TaskQueue{
    public:
        TaskQueue() = default;
        ~TaskQueue() = default;

        void pushTask(Task<T> task);
        void pushTask(callback func,void* arg);
        Task<T> takeTask();
        inline int getTaskNum(){
            return task_queue.size();
        }
    private:
        std::mutex  m_lock;
        std::deque<Task> task_queue;  
};

队列类的定义:

#include"Task.h"
template<typename T>
void TaskQueue<T>::pushTask(Task<T> task)
{
    m_lock.lock();
    task_queue.push_back(task);
    m_lock.unlock();
}

template<typename T>
void TaskQueue<T>::pushTask(callback func,void* arg)
{
    m_lock.lock();
    task_queue.push_back(Task<T>(func,arg));
    m_lock.unlock();
}
  
template<typename T>
Task<T> TaskQueue<T>::takeTask()
{
    m_lock.lock();
    Task<T> task = task_queue.front();
    task_queue.pop_front();
    m_lock.unlock();
    return task;
}

2.线程池

类的声明:

#pragma once

#include"Task.h"
#include<condition_variable>
#include<vector>
#include<map>

template<typename T>
class threadPool{
    public:
        threadPool(int min,int max);
        ~threadPool();
        void pushTask(Task<T> task);
        int getBustNum();
        int getLiveNum();
        void exitThread();
    private:
        static void* manager(void*);
        static void* worker(void*);
    private:
        TaskQueue<T>* m_task_queue;
        std::thread* m_manager;
        std::vector<std::thread*> m_workers;
        int m_minNum;
        int m_maxNum;
        int m_liveNum;
        int m_busyNum;
        int m_destroyNum;
        std::mutex m_pool_lock;
        std::condition_variable m_cv;
        bool m_isDestroy;
        static const int STEP = 2;
};

类的定义:

#include"thread_pool.h"
#include<iostream>
#include<string>
#include<thread>

template<typename T>
threadPool<T>::threadPool(int min,int max):m_minNum(min),m_maxNum(max)
{
    m_task_queue = new TaskQueue<T>;
    if(!m_task_queue)
    {
        std::cout << "malloc task queue failed,exit..." << std::endl;
        break;
    }
    m_busyNum = 0;
    m_liveNum  = min;
    m_destroyNum = 0;
    m_isDestroy = false;
    m_manager = new std::thread(manager,std::ref(this));
    for(int i = 0;i < min,i++)
    {
        m_workers.emplace_back(new std::thread(worker,std::ref(this)));
    }
}


template<typename T>
threadPool<T>::~threadPool()
{
    m_isDestroy = true;
    m_manager->join(); 
    m_cv.notify_all();//唤醒所有阻塞的线程,由线程自己做销毁
    if(m_task_queue) delete m_task_queue;
}

template<typename T>
void threadPool<T>::pushTask(Task<T> task)
{
    if(m_isDestroy)
    return;
    m_task_queue->pushTask(task);
    m_cv.notify_one();
}

template<typename T>
int threadPool<T>::getBustNum()
{
    m_pool_lock.lock();
    int busyNum = m_busyNum;
    m_pool_lock.unlock();
    return busyNum;
}

template<typename T>
int threadPool<T>::getLiveNum()
{
    m_pool_lock.lock();
    int liveNum = m_liveNum;
    m_pool_lock.unlock();
    return liveNum;
}


template<typename T>
void* threadPool<T>::worker(void* arg)
{
    threadPool* pool = static_cast<threadPool*>(arg);//传入类的this指针
    while(true)
    {
        pool->m_pool_lock.lock();
        while(pool->m_task_queue->getTaskNum() == 0 && !pool->m_isDestroy)
        {
            pool->m_cv.wait(pool->m_pool_lock);
            if(pool->m_destroyNum > 0)
            {
                pool->m_destroyNum--;
                pool->m_pool_lock.unlock();
                pool->exitThread();
            }
        }
        if(pool->m_isDestroy)
        {
            pool->m_pool_lock.unlock();
            pool->exitThread();
        }

        Task<T> task = pool->m_task_queue->takeTask();
        pool->m_busyNum++;
        pool->m_pool_lock.unlock();
        std::cout << "thread:" << std::this_thread::get_id() << " is running" << std::endl;
        task.function(task.arg);
        delete task.arg;
        task.arg = nullptr;
        std::cout << "thread:" << std::this_thread::get_id() << " finished work" << std::endl;
        pool->m_pool_lock.lock();
        pool->m_busyNum--;
        pool->m_pool_lock.unlock();
    }
    return nullptr;
}

template<typename T>
void* threadPool<T>::manager(void* arg)
{
    threadPool* pool = static_cast<threadPool*>(arg);//传入类的this指针
    while(!pool->m_isDestroy)
    {
        sleep(5);
        pool->m_pool_lock.lock();
        int taskNum = pool->m_task_queue.size();
        int busuNUm = pool->getBustNum();
        int liveNum = pool->getLiveNum();
        pool->m_pool_lock.unlock();
        if(taskNum >liveNum && liveNum < pool->m_maxNum)
        {
            pool->m_pool_lock.lock();
            int cnt = 0;
            for(int i = 0;i < pool->m_maxNum && cnt < STEP && pool->getLiveNum() < pool->m_maxNum;i++)
            {
                m_workers.emplace_back(new std::thread(worker,std::ref(pool)));
                cnt++;
                pool->m_liveNum++;
            }
            pool->m_pool_lock.unlock();
        }
        if(busuNUm*2 < liveNum && liveNum >pool->m_minNum)
        {
            pool->m_pool_lock.lock();
            pool->m_destroyNum = STEP;
            pool->m_pool_lock.unlock();
            for(int i = 0 ;i < STEP;i++)
            {
                pool->m_cv.notify_one();
            }
        }
    }
    return nullptr;
}

template<typename T>
void threadPool<T>::exitThread()
{
    std::thread::id tid = std::this_thread::get_id();
    for(std::vector<std::thread*>::iterator it = m_workers.begin();it != m_workers.end();it++)
    {
        std::thread* pthread(nullptr);
        if((*it)->get_id() == tid)
        {
            pthread = *it;
            (*it)->join();
            delete pthread;
            break;
        }
    }
    m_workers.erase(it);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值