最近在实现一个跨平台项目,需要用到线程池,然后c++本身不自带线程池,就只能自己实现了,这里只是实现了一个包含线程池基础功能简单版本的例子,做个记录
头文件 ThreadPool.h
#pragma once
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<memory>
#include<queue>
#include<vector>
#include<atomic>
class Task
{
public:
Task()
{
}
virtual ~Task()
{
}
virtual void UnderTake() = 0;//具体任务子类实现
};
#define MAX_THREADNUM 50
#define MIN_THREADNUM 1
#define MAX_TASKNUM 100
class ThreadPool
{
public:
//c++11 magic static 单例模式
static ThreadPool* GetSingleton()
{
static ThreadPool pool;
return &pool;
}
bool Init(unsigned int threadNum);
void Fini();
void PostTask(Task* task);
bool SetThreadNum(unsigned int threadNum);
~ThreadPool()
{
if (m_bInit)
{
Fini();
}
}
private:
ThreadPool(ThreadPool&) = delete;
ThreadPool& operator=(const ThreadPool&) = delete;
ThreadPool()
:m_bInit(false)
,m_bRuning(false)
,m_postingTask(0)
{
}
private:
bool m_bInit;//线程池是否已初始化
std::atomic<int> m_postingTask;
std::atomic<bool> m_bRuning;//运行标志,控制所有线程停启
std::queue<Task*> m_taskQ;//任务队列
std::mutex m_mtx;//任务队列锁
std::condition_variable m_cond;//条件变量
std::vector<std::thread> m_vecThread;//线程
unsigned int m_threadNum;//线程数量
};
源文件 ThreadPool.cpp
#include "ThreadPool.h"
bool ThreadPool::Init(unsigned int threadNum)
{
if (m_bInit)
{
return true;
}
if (threadNum < MIN_THREADNUM)
{
threadNum = MIN_THREADNUM;
}
if (threadNum > MAX_THREADNUM)
{
threadNum = MAX_THREADNUM;
}
m_bRuning = true;
for (unsigned int i = 0; i < threadNum; ++i)
{
m_vecThread.emplace_back(std::thread( [this]
{
while (m_bRuning)
{
Task* task = NULL;
{
std::unique_lock<std::mutex> lock(m_mtx);
m_cond.wait(lock, [this] { return !m_bRuning || !m_taskQ.empty(); });
if (!m_bRuning || m_taskQ.empty())
{
return;
}
task = m_taskQ.front();
m_taskQ.pop();
}
if (task != NULL)
{
task->UnderTake();
delete task;
task = NULL;
}
}
}));
}
m_threadNum = threadNum;
m_bInit = true;
return true;
}
void ThreadPool::PostTask(Task* task)
{
if (task == NULL || !m_bInit || !m_bRuning)
{
return;
}
m_postingTask.fetch_add(1);
std::unique_lock<std::mutex> lock(m_mtx);
if (m_taskQ.size() >= MAX_TASKNUM)
{
return;
}
m_taskQ.push(task);
m_cond.notify_one();
m_postingTask.fetch_sub(1);
}
void ThreadPool::Fini()
{
if (!m_bInit)
{
return;
}
m_bRuning = false;
m_cond.notify_all();
for (auto& iter : m_vecThread)
{
if (iter.joinable())
{
iter.join();
}
}
while (!m_taskQ.empty())
{
Task* task = m_taskQ.front();
if (task != nullptr)
{
delete task;
task = nullptr;
}
m_taskQ.pop();
}
m_bInit = false;
}
bool ThreadPool::SetThreadNum(unsigned int threadNum)
{
int nNum = m_threadNum - threadNum;
if (threadNum < MIN_THREADNUM || threadNum>MAX_THREADNUM || nNum > 0)
{
return false;
}
for(int i=0; i<nNum; ++i)
{
m_vecThread.emplace_back(std::thread([this]
{
while (m_bRuning)
{
Task* task = NULL;
{
std::unique_lock<std::mutex> lock(m_mtx);
m_cond.wait(lock, [this] { return !m_bRuning || !m_taskQ.empty(); });
if (!m_bRuning || m_taskQ.empty())
{
return;
}
task = m_taskQ.front();
m_taskQ.pop();
}
if (task != NULL)
{
task->UnderTake();
delete task;
task = NULL;
}
}
}));
}
return true;
}
经过简单测试,功能可用,以往实现线程池,具体性能瓶颈往往在线程取任务的时候,这里在让每个线程去竞争任务;利用了一些c++11的新特性,例如条件变量,原子变量及原子操作,lamada表达式,emplace_back,boost库线程也集成到c++11了,方便可用,内存管理后面还可以使用智能指针继续优化。