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