C++实现线程池,支持添加类的成员函数

本文介绍了CThreadPool类,用于管理线程池,包括线程的创建、任务的添加与执行,以及线程的启动、停止和任务调度。通过实例展示了如何使用模板函数和绑定操作来添加不同类型的任务。
摘要由CSDN通过智能技术生成

概念

线程池主要用来实现多个线程管理,合理的复用线程、将线程的创建和任务的执行解耦开来。利用线程池来复用已经创建的线程来降低频繁创建和销毁线程所带来的资源消耗。同时线程池其实就是一种多线程处理形式,可以把一项复杂工作划分为多个任务,将这些任务添加到线程池队列中,然后线程池里线程后自动启动这些任务。
在这里插入图片描述

线程.h文件

class CThreadPool
    {
    public:
        /**
         * @brief CThreadPool 线程构造函数
         * @param uiInitTheadCnt 线程数量
         */
        CThreadPool(size_t uiInitTheadCnt);
        ~CThreadPool()
        {
            if(m_isRunning)
            {
                stop();
            }
        }
    public:
        template<typename xClass,typename xReturn,typename...xParam>
        void AddTask(xClass* pThis,xReturn(xClass::* pfn)(xParam...),xParam...lp);
        template<typename xReturn,typename... xParam>
        /**
         * @brief AddTask 添加执行任务
         * @param lp 依次为 函数指针、类对象、参数
         *
         */
        void AddTask(xReturn(*pfn)(xParam...),xParam...lp);
        /**
         * @brief AddTask 添加任务函数
         * @param t 函数指针
         */
        void AddTask(std::function<void()>t);
        /**
         * @brief ThreadLoop
         * 线程池管理线程循环函数,查询当前任务队列是不为空
         */
        void ThreadLoop();
        /**
         * @brief stop
         * 线程池停止函数
         */
        void stop();
        /**
         * @brief start
         * 线程池启动函数
         */
        void start();
        std::function<void()> GetTask();
    private:
        std::function<void()> m_Fp;   //函数指针
        std::queue<std::function<void()>> m_taskQueue; //任务队列
        size_t m_uiInitTheadCnt;
        std::atomic_bool m_isRunning;
        std::condition_variable m_cond;//条件变量
        std::vector<std::thread*> m_vecThreads;
        std::mutex m_mutex;
        std::mutex m_queueMutex;
    };

线程.cpp实现

	CThreadPool::CThreadPool(size_t uiInitTheadCnt):m_uiInitTheadCnt(uiInitTheadCnt)
        {

        }
        template<typename xClass,typename xReturn,typename ...xParam>
        void CThreadPool::AddTask(xClass* pThis,xReturn(xClass::* pfn)(xParam...),xParam...lp)
        {
            AddTask(std::bind(pfn,pThis,lp...));
        }
        template<typename xReturn,typename ...xParam>
        void CThreadPool::AddTask(xReturn(*pfn)(xParam...),xParam...lp)
        {
            AddTask(std::bind(pfn,lp...));
        }
        void CThreadPool::stop()
        {
            m_isRunning=false;
            m_cond.notify_all();
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
        std::function<void()> CThreadPool::GetTask()
        {
            std::unique_lock<std::mutex> lock(m_queueMutex);  //利用条件锁,避免一直查询队列是否为空,有些解决管理线程的资源消耗问题。
            m_cond.wait(lock,[this]{return !m_isRunning||!m_taskQueue.empty();});
            std::function<void()> Task=nullptr;
            if(!m_taskQueue.empty())
            {
                Task=m_taskQueue.front();
                m_taskQueue.pop();
            }
            return Task;
        }
        void CThreadPool::ThreadLoop()
        {
            while(m_isRunning)
            {
                std::function<void()> Task=GetTask();
                if(Task)
                {
                    Task();
                }
                else
                {
                    QThread::usleep(5000);
                }
            }
        }
        void CThreadPool::start()
        {
            m_vecThreads.clear();
            m_isRunning=true;
            for(size_t i=0;i<m_uiInitTheadCnt;i++)
            {
                m_vecThreads.push_back(new std::thread(std::bind(&CThreadPool::ThreadLoop,this)));
            }
        }
        void CThreadPool::AddTask(std::function<void()>t)
        {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_taskQueue.emplace(t);
            m_cond.notify_one();
        }

测试程序代码

由于缩写的线程池支持添加类的成员函数,故创建了一个控制台程序,添加了一个测试线程类(TestThreadPool)对其进行测试。测试程序如下所示:

main.cpp

TestThreadPool test; //线程池测试
 test.testFun();
 while(1);

TestThreadPool 代码

unsigned int g_uiIndex=0;
TestThreadPool::TestThreadPool()
{

}
void TestThreadPool::TaskSleep(unsigned int TimeMs)
{
    std::this_thread::sleep_for(std::chrono::seconds(TimeMs));
    m_Mutex.lock();
    g_uiIndex++;
    std::cout<<"Index="<<g_uiIndex<<" Thread ID="<<std::this_thread::get_id()<<" Sleep "<<TimeMs<<"s"<<endl;
    m_Mutex.unlock();
}
void TestThreadPool::testFun()
{
    CThreadPool *ThreadPool=new CThreadPool(3);
    for(int i=0;i<5;i++) //5s
    {
        ThreadPool->AddTask(std::bind(&TestThreadPool::TaskSleep,this,1));
    }
    for(int i=0;i<3;i++) //3*2=6s
    {
        ThreadPool->AddTask(std::bind(&TestThreadPool::TaskSleep,this,2));
    }
    for(int i=0;i<3;i++) //3*3=9s
    {
        ThreadPool->AddTask(std::bind(&TestThreadPool::TaskSleep,this,3));
    }
    ThreadPool->start();
}

执行结果

Index=1 Thread ID=2 Sleep 1s
Index=2 Thread ID=4 Sleep 1s
Index=3 Thread ID=3 Sleep 1s
Index=4 Thread ID=4 Sleep 1s
Index=5 Thread ID=2 Sleep 1s
Index=6 Thread ID=3 Sleep 2s
Index=7 Thread ID=2 Sleep 2s
Index=8 Thread ID=4 Sleep 2s
Index=9 Thread ID=3 Sleep 3s
Index=10 Thread ID=2 Sleep 3s
Index=11 Thread ID=4 Sleep 3s

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蛮v蛮

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

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

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

打赏作者

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

抵扣说明:

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

余额充值