本文主要介绍C++中线程池的实现以及C++11中新特性(仿函数、线程、互斥量、原子、条件变量等)的使用,最终会实现一个简易的线程池,可支持传参不传参等任务。
目录
一、线程池的用途
1、线程池的作用
频繁的创建和销毁线程会产生大量的程序资源消耗。使用线程池来管理线程的创建和销毁, 有助于提高线程创建和销毁过程的效率。线程池的本质就是提前创建一堆线程,在程序需要使用线程来执行任务的时候,将任务放置到线程池中交给未执行任务的线程执行,从而提高了程序的运行效率,提高了线程的利用率。
二、线程池的实现思路
1、线程池类头文件
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <iostream>
#include <thread>
#include <functional>
#include <queue>
#include <vector>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <chrono>
class CThreadPool
{
using Task = std::function<void()>;
private:
CThreadPool();
~CThreadPool();
CThreadPool(const CThreadPool&) = delete;
CThreadPool& operator=(const CThreadPool&) = delete;
public:
static CThreadPool& GetInstance();
void SetMaxThreadNum(const int iCount);
void OnStart();
void OnStop();
void AppendTask(const Task& _task);
private:
void DoWork();
private:
std::atomic_bool m_bIsRunning{false};
unsigned short m_usThreadNum{2};
std::vector<std::thread> m_vctThreads;
std::queue<Task> m_queTasks;
std::condition_variable m_cv;
std::mutex m_mtx;
};
#endif /* THREADPOOL_H */
2、线程池类源文件
#include "../include/threadpool.h"
CThreadPool::CThreadPool()
{
}
CThreadPool::~CThreadPool()
{
OnStop();
}
CThreadPool& CThreadPool::GetInstance()
{
static CThreadPool instance;
return instance;
}
void CThreadPool::SetMaxThreadNum(const int _iCount)
{
m_usThreadNum = _iCount;
}
void CThreadPool::OnStart()
{
m_bIsRunning = true;
for (int iIndex = 0; iIndex < m_usThreadNum; ++iIndex)
{
m_vctThreads.emplace_back(std::thread(&CThreadPool::DoWork, this));
}
}
void CThreadPool::OnStop()
{
{
std::unique_lock<std::mutex> ulock(m_mtx);
m_bIsRunning = false;
m_cv.notify_all();
}
for (auto& td : m_vctThreads)
{
if (td.joinable())
{
td.join();
}
}
}
void CThreadPool::AppendTask(const Task& _task)
{
std::unique_lock<std::mutex> ulock(m_mtx);
m_queTasks.push(_task);
m_cv.notify_one();
}
void CThreadPool::DoWork()
{
while(m_bIsRunning)
{
Task task;
{
std::unique_lock<std::mutex> ulock(m_mtx);
if (!m_queTasks.empty())
{
task = m_queTasks.front();
m_queTasks.pop();
}
else if (m_queTasks.empty() && m_bIsRunning)
{
m_cv.wait(ulock);
}
}
if (task)
{
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
task();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << (std::chrono::time_point_cast<std::chrono::microseconds>(end) -
std::chrono::time_point_cast<std::chrono::microseconds>(start)).count() /1000000.00<< std::endl;
}
}
}
3、使用线程池
#include "include/threadpool.h"
std::mutex mtx;
void Test(int iValue)
{
std::unique_lock<std::mutex> ulock(mtx);
std::cout<<std::this_thread::get_id()<<" thread execute...."<<iValue<<std::endl;
}
int main(int argc, char* argv[])
{
CThreadPool::GetInstance().SetMaxThreadNum(4);
CThreadPool::GetInstance().OnStart();
for (int i=0; i<100; i++)
{
CThreadPool::GetInstance().AppendTask(std::bind(Test, i));
}
std::this_thread::sleep_for(std::chrono::seconds(10));
CThreadPool::GetInstance().OnStop();
return 0;
}
三、不足和缺陷
在上文中线程池没有实现任务的优先级,有时还需要使用任务的执行结果,这些都没有处理,后续在完善,欢迎大家指导和提出宝贵意见。