1.线程池的基本概念
所谓的线程池就是事先创建好指定数目的线程,当同步队列为空的时候,线程全部处于等待状态,一旦同步队列被添加了事务,线程池就从同步队列中取事务并进行处理,处理完成之后又会重新获取同步队列中的事务。如果同步队列为空,就再次处于等待状态;如果没有空闲线程但是有新任务产生就放在同步队列中,等待线程执行完当前事务之后才能执行。
线程池的优点:
①降低资源的消耗:通过重复利用线程可以减少因频繁创建和销毁线程所带来的消耗。
②提高响应速度:当执行同步队列中的事务的时候,省去了创建线程的时间。
③提高线程的可管理性:线程是稀缺资源,如果无限制的创建线程,不仅会消耗系统的资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程池的缺点:
①适应于生存周期较短的任务,不适应于又长又大的任务。
②不能对线程池中的任务设置优先级。
③不能标识线程的各个状态:比如启动线程、终止线程。
④对于任意给定的应用程序域,只能允许一个线程池与之对应。
⑤线程池中的所有线程都处于多线程单元中,如果想把线程放在单线程单元中,线程池就废掉了。
2.使用线程池的目的
由于创建线程存在一定的开销,无止尽的开新的线程会给系统产生大量的消耗,所以通过线程池使得线程能够重用从而处理无限的事务,避免每次使用线程都初始化。
3.线程池的工作原理
3.1主要组成:
(1)同步队列:以链表的形式创建一个同步队列,同步队列的主要工作就是通过Put()函数向队列里面添加事务,通过Get()函数从队列里面取出事务。
(2)线程池:主要由线程组(注:线程组里面存放的时thread类型的共享只能指针,指向工作的线程)构成,通过Start()函数向线程组中添加numThreads个线程,并使得每一个线程调用RunThread()函数来获取同步队列的事务并执行事务;通过Stop()函数停止线程池的工作。
3.2工作情况:
情况1:同步队列为空,主程序没有向同步队列中添加事务,线程池中的线程全部处于等待状态
情况2:同步队列满了,任务添加此时进入等待状态,等同步队列不满,继续执行添加工作
情况3:同步队列为空,主程序执行任务添加的数量小于线程的数量
情况4:同步队列不为空,但也没有满,线程池中所有的线程都在执行相应的事务,于此同时主程序向同步队列中添加事务。
3.3代码实现:
#include <iostream>
#include <mutex>
#include <list>
#inlcude <functional>
#include <condition_variable>
using namespace std;
//共享队列:
template <class T>
class SyncQueue
{
private:
list<T> m_queue;
mutex m_mutex;
condition_variable m_IsFull;//客户端从共享队列中取事务的时候需要判断是否满了,满了就等待
condition_variable m_IsEmpty;//服务端从共享队列总取事务的时候需要判断是为为空,空了就等待
bool NeedStop;
int maxSize;
public:
SyncQueue(int size):maxSize(size),NeedStop(false){}
~SynQueue()
{
Stop();
}
//往共享队列中添加事务
void Put(T& task)
{
Add(task);
}
void Put(T&& task)
{
Add(std::forward<T>(task));
}
void Add(T&& task)
{
unique_lock<mutex>locker(m_mutex);
IsFull.wait(locker,[]->bool{return NeedStop||NotFull();});
if(NeedStop)
{
return;
}
m_queue.push_back(std::forward<T>(tesk));
IsEmpty.notify_one();
}
//从共享队列中取出事务
void Get(list<T>& ls )//取出全部事务
{
unique_lock<mutex>locker(m_mutex);
IsEmpty.wait(locker,[]->bool{return NeedStop||NotEmpty();});
if(NeedStop)
{
return;
}
ls=std::move(m_queue);
IsEmpty.notify_one();
}
void Get(T& tmp )//取出一个事务
{
unique_lock<mutex>locker(m_mutex);
IsEmpty.wait(locker,[]->bool{return NeedStop||NotEmpty();});
if(NeedStop)
{
return;
}
tmp=m_queue.front();
queue.pop();
IsEmpty.notify_one();
}
//停止当前共享队列的运行
void Stop()
{
{
unique_lock<mutex>locker(m_mutex);
NeedStop=true;
}
IsEmpty.notify_all();
IsFull.notify_all();
}
bool NotEmpty()
{
unique_lock<mutex>locker(m_mutex);
return !m_queue.empty();
}
bool NotFull()
{
unique_lock<mutex>locker(m_mutex);
return !m_queue.size()==maxSize;
}
}
using Task=std::functional<void(void)>;
int MaxTaskCount=100;//规定线程组的最大容量
//线程池:
class ThreadPool()
{
private:
SyncQueue<Task> m_queue;
list<make_shared<std::thread>>m_thread_group;
atomic_bool running;
std::once_flag m_flag;
void RunThread()
{
while(running)
{
std::list<Task> list;
m_queue.Get(list);
for(auto t:list)
{
if(!running)
{
return;
}
t();
}
}
}
void StopThreadPool()
{
m_queue.Stop();
running=false;
for(auto& th:m_thread_group)
{
if(th)
{
th->join();
}
}
m_thread_group.clear();
}
public:
ThreadPool():m_queue(MaxTaskCount)
{}
~ThreadPool()
{
Stop();
}
//将事务添加到共享队列中
void AddTask(Task&& t)
{
m_queue.push_back(std::forward<Task>(t));
}
void AddTask(const Task& t)
{
m_queue.push_back(t);
}
//开始线程池的工作
void start(int NumThreads=thread::hardware_concurrency())
{
running=true;
for(int i=0;i<NumThreads;++i)
{
m_thread_group.push_back(make_shared<thread>(&ThreadPool::RunThread,this));
}
}
//停止线程池的工作
void Stop()
{
std::call_once(m_flas,[this]{StopThreadPool();});
}
}
//测试代码:
void fun(thread::id thdid )
{
cout << thdid << endl;
}
void funa(ThreadPool& pool)
{
cout << "void funa" << endl;
for (int i = 0; i < 10; ++i)
{
thread::id thdid = this_thread::get_id();
Task ft = std::bind(fun, thdid);
pool.AddTask(ft);//将事务添加到队列中
}
}
void TestThreadPool()
{
ThreadPool pool;
pool.Start(5);//首先线程池启动创建五个线程,然后每一个线程开始启动运行,向队列中取事务发现没有事务,因此挂起
std::this_thread::sleep_for(std::chrono::seconds(2));
std::thread tha(funa, std::ref(pool));//启动线程tha,调用funa函数,这个函数会给线程池里面的队列添加事务—>函数fun
tha.join();
}
int main()
{
TestThreadPool();
return 0;
}