//代码实现
#include<iostream>
#include<memory>//内存管理
#include<atomic>//原子操作
#include<functional>
#include<thread>
#include<list>
#include<mutex>
#include<condition_variable>
using namespace std;
//异步 Asyn
//同步 Sync
template<class T>
class SyncQueue
{
public:
SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){}
~SyncQueue(){}
void Put(const T& x) { Add(x); }
void Put(T&& x) { Add(std::forward<T>(x)); }
void Take(std::list<T>& list)//全部提取任务
{
std::unique_lock<std::mutex>locker(m_mutex);
m_notEmpty.wait(locker, [this]() {return m_needStop || NotEmpty(); });
//while (!m_needStop && !NotEmpty())
//{
// m_notEmpty.wait(locker);
//}与上边等价
if (m_needStop)
{
return;
}
list = std::move(m_queue);//把m_queue队列里边的任务全部移动到list里边
m_notFull.notify_one();
}
void Take(T& t)
{
std::unique_lock<std::mutex>locker(m_mutex);
m_notEmpty.wait(locker, [this]() {return m_needStop || NotEmpty(); });
//while (!m_needStop && !NotEmpty())
//{
// m_notEmpty.wait(locker);
//}与上边等价
if (m_needStop)
{
return;
}
t = m_queue.front();
m_queue.pop_front();//取一个
m_notFull.notify_one();
//唤醒因任务满了而被阻塞的线程,提示可以继续添加任务了
}
void Stop()
{//不能直接将m_needStop置为真(直接置为真,会导致上边的添加和执行都不能执行),
{
std::unique_lock<std::mutex>locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
}
bool Empty()const
{
std::unique_lock<std::mutex>locker(m_mutex);
return m_queue.empty();
}
size_t Size()const
{
std::unique_lock<std::mutex>locker(m_mutex);
return m_queue.size();
}
bool Full()const
{
std::unique_lock<std::mutex>locker(m_mutex);
return m_queue.size() >= m_maxSize;
}
int Count()const
{
return m_queue.size();
}
private:
bool NotFull()const
{
bool full = m_queue.size() > m_maxSize;
if (full)
{
cout << "缓冲区满了,需要等待..." << endl;
}
return !full;
}
bool NotEmpty()const
{
bool empty = m_queue.empty();
if (empty)
{
cout << "缓冲区空了,需要等待...异步层线程ID:" << this_thread::get_id << endl;
}
return !empty;//与逻辑一致
}
//任务的添加和取出是一个同步过程,这里必须使用互斥量
template<class F>
void Add(F&& x)//添加任务
{
std::unique_lock<std::mutex>locker(m_mutex);//
//条件变量的wait方法里边有一个线程容器
m_notFull.wait(locker, [this]()
{//条件变量等待的时候获取锁,等待当前对象里边的值
//值:是否处于停止状态或缓冲区是否未满
return m_needStop || NotFull();
//NotFull()返回为假时,说明此时已经到达上限,这是就需要把放任务的线程给挂起来(挂起来指的就是将线程暂时放在对应条件变量的wait线程容器中)
});
if (m_needStop)
{
return;
}
//如果缓冲区不停止工作,那么继续添加任务
m_queue.push_back(std::forward<F>(x));//完美转发技术
m_notEmpty.notify_one();//如果同步队列为空,那么执行任务的线程就会被挂起,知到添加任务后再唤醒
//m_notEmpty.notify_all();//为什么不唤醒所有呢?防止发生惊群现象
}
private:
std::list<T>m_queue;//缓冲区==同步队列 可以添加任何东西
std::mutex m_mutex;//互斥量
std::condition_variable m_notEmpty;//不为空 当同步队列为空时,就把执行任务的线程挂在此条件变量上
std::condition_variable m_notFull;//没有满 当同步队列满时,就把添加任务的线程挂在此条件变量上
int m_maxSize;//任务量上限
bool m_needStop;//停止同步队列
};
const int MaxTackCount = 5;//最大线程个数
class ThreadPool
{
public:
//using Task = std::function<void()>;
// 获取当前系统逻辑线程的个数
using Task = void(*)();
ThreadPool(int numThreads = std::thread::hardware_concurrency()):m_queue(MaxTackCount)
{
Start(numThreads);
}
~ThreadPool()
{
Stop();
}
void Stop()
{
std::call_once(m_flag, [this]() {StopThreadGrounp(); });//只允许运行一次
}
void AddTack(Task&& task)
{
m_queue.Put(std::forward<Task>(task));
}
void AddTack(const Task& task)
{
m_queue.Put(task);
}
//创建线程并添加到线程池
void Start(int numThreads)
{
m_running = true;//开始运行
for (int i = 0; i < numThreads; ++i)
{//采用共享智能指针得目的是:当线程池结束的时候,list里边的线程会自动被销毁
m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));
//创建一个线程,我们需要给线程给定一个地址,线程需要和函数联系起来,就是RunInThread,this作为参数传递给此函数
//thread tha(&ThreadPool::RunInThread, this);
}
}
private:
void RunInThread()
{
while (m_running)
{
std::list<Task>list;
m_queue.Take(list);//一次全部取完
//Task task;//取一个
//m_queue.Take(task);
for (auto& task: list)
{
if (!m_running)
{
return;
}
task();
}
}
}
void StopThreadGrounp()
{
m_queue.Stop();
m_running = false;
for (auto& thread : m_threadgroup)
{
if (thread)
{
thread->join();//阻塞当前线程
}
}
m_threadgroup.clear();//清除整个线程
}
std::list < std::shared_ptr<std::thread>>m_threadgroup;//存放线程
SyncQueue<Task>m_queue;//任务
atomic_bool m_running;//是否处于运行状态
std::once_flag m_flag;//让程序只运行一次
};
void PrintA()
{
cout << "同步线程1 线程ID:" <<endl;
}
void funa(ThreadPool& pool)
{
auto thdid = this_thread::get_id();
for (int i = 0; i < 10; ++i)
{
pool.AddTack(PrintA);
}
}
void PrintB()
{
cout << "同步线程1 线程ID:" << endl;
}
void funb(ThreadPool& pool)
{
auto thdid = this_thread::get_id();
for (int i = 0; i < 10; ++i)
{
pool.AddTack(PrintB);
}
}
int main()
{
ThreadPool pool(2);
std::thread thd1(funa, std::ref(pool));
std::thread thd2(funb, std::ref(pool));
/*
std::thread thd1([&pool] {
for (int i = 0; i < 10; ++i)
{
auto thdid = this_thread::get_id();
pool.AddTack([thdid] {
cout << "同步线程1 线程ID:" << thdid << endl;
});
}
});
std::thread thd2([&pool] {
for (int i = 0; i < 10; ++i)
{
auto thdid = this_thread::get_id();
pool.AddTack([thdid] {
cout << "同步线程1 线程ID:" << thdid << endl;
});
}
});
*/
this_thread::sleep_for(std::chrono::seconds(2));
getchar();
pool.Stop();
thd1.join();
thd2.join();
return 0;
}