一、什么是线程池
线程池就是被统一管理的若干个线程。这些线程在程序开始时就被创建,当程序需要另外一个线程执行代码时,就从线程池去取,不用每次都开辟线程。
二、线程池的优势
- 线程池可以控制开辟线程的数量,避免请求过多时创建的线程过多,造成线程阻塞。
- 提高响应速度,降低资源消耗。每次开辟线程和销毁都是资源消耗,线程池这个避免重复的创建和销毁线程。
三、代码实现
3.1 头文件定义
下面定义了一个线程池的类,他大概一共有四部分成员参数组成:
- 任务队列
- 线程队列
- 线程池创建和销毁
- 公共锁和私有成员
/*
Datetime:2020/8/21
By LiuZhenguang
*/
#ifndef _THREADPOOL__H
#define _THREADPOOL__H
#include <vector>
#include <mutex>
#include <thread>
#include <deque>
#include <condition_variable>
#include <functional>
typedef std::function<void()> T_TASK;
typedef std::deque<T_TASK> T_TASK_QUEUE;
typedef std::vector<std::thread*> T_THREAD_QUEUE;
class ThreadPool{
public:
~ThreadPool();
ThreadPool(int defSize=3);
void stopThreadPool();
void startThreadPool();
bool bIsThreadPoolStart();
bool bIsThreadPoolStart;
T_TASK_QUEUE taskQueue;
T_TASK getTaskFrmQueue();
void addTask2Queue(const Task& t);
void ThreadLoop();
T_THREAD_QUEUE threadQueue;
private:
int threadSize;
ThreadPool(const ThreadPool& t);//private禁止拷贝构造函数被调用
const ThreadPool operator=(const ThreadPool& t);
std::mutex m_mutex;
std::condition_variable m_cond;
};
#endif
3.2 源文件定义
#include "ThreadPool.h"
#include <iostream>
/**************************
*构造函数
***************************/
ThreadPool::ThreadPool(int defSize):threadSize(defSize),m_mutex(),m_cond(),bIsThreadPoolStart(false)
{
threadSize=defSize;
startThreadPool();
}
/**************************
*线程初始化并启动
***************************/
void ThreadPool::startThreadPool()
{
this.bIsThreadPoolStart = true;
this.threadQueue.reserve(threadSize);
for (int i=0; i<threadSize; ++i)
{
//创建线程,传入线程函数。使用bind是因为必须使用对象的函数地址
threadQueue.push_back(new std::thread(std::bind(&ThreadPool::ThreadLoop, this)));
}
}
/**************************
*线程函数,一直尝试获取任务
***************************/
void ThreadPool:: ThreadLoop()
{
while (bIsThreadPoolStart)
{
T_TASK task = getTaskFrmQueue();
if (task){
task();
}
}
}
/**************************
*取任务
***************************/
Task ThreadPool::getTaskFrmQueue()
{
std::unique_lock<std::mutex> lock(m_mutex);
while (taskQueue.empty() && bIsThreadPoolStart)
{
m_cond.wait(lock);//条件变量等待锁阻塞,等待addTask或析构时的notify all()
}
T_TASK task;
if (!taskQueue.empty() && bIsThreadPoolStart)
{
task = taskQueue.front();
taskQueue.pop_front();
if (TaskQueueSize_ > 0)
{
m_cond.notify_one();
}
}
return task;
}
/**************************
* 添加任务
***************************/
void ThreadPool:: addTask(const Task& t)
{
std::unique_lock<std::mutex> lock(m_mutex);
taskQueue.push_back(t);
m_cond.notify_all();
}
/**************************
* 析构函数
***************************/
ThreadPool::~ThreadPool()
{
stopThreadPool();
}
/**************************
* 关闭线程池
***************************/
void ThreadPool:: stopThreadPool()
{
bIsThreadPoolStart = false;
std::unique_lock<std::mutex> m_lock(m_mutex);//获得任务队列锁,停止添加或取任务
m_cond.notify_all(); //唤醒所有其他线程
for (auto thread : threadQueue)
{
thread->join();//主线程等待所有子线程结束
delete thread;
}
threadQueue.clear();
}
问题
1、取任务也没有为那个任务分配线程、看着是主线程在取任务并执行
2、std::bind()机制链接
3、std::function()链接