半同步半异步线程池
再处理大量并发任务的时候,如果按照传统的方式,来一个任务请求,对应一个线程来处理请求任务,大量的线程创建和销毁将消耗过多的系统资源,还增加了线程运行环境切换的开销,而通过线程池技术就可以很好地解决这些问题;线程池技术通过再系统中预先创建一定量的线程,当任务请求到来时从线程池中分配一个预先创建的线程去处理任务,线程在处理完任务之后还可以重用,不会销毁,而是等待下次任务的到来
这样,通过线程池能避免大量的线程创建和销毁动作,从而节省系统资源,这样做的一个好处是,对于多核处理器,由于线程会被分配到多个CPU,会提高并行处理的效率;另一个好处是每个线程独立阻塞,可以防止主线程被阻塞而使主流程被阻塞,导致其他的请求得不到相应的问题
线程池分为半同步半异步线程池和领导者追随者线程池,本章主要介绍半同步半异步线程池,这种线程池在实现上更简单,使用得比较多,也比较方便
- 半同步半异步线程池分为三层
- 同步服务层:它处理来自上层的任务请求,上层的请求可能是并发的,这些请求不是马上就会被处理,而是将这些任务放到一个同步排队层中,等待处理
- 同步排队层:来自上层的任务请求都会加到排队层中等待处理
- 异步服务层,这一层中会有多个线程同时处理排队层中的任务,异步服务器从同步排队层中取出任务并行的处理
同步队列
template<typename T>
class SyncQueue
{
public:
SyncQueue(int maxSize) :m_max_Size(maxSize), m_needStop(false)
{}
void Put(const T& x)
{
Add(x);
}
void Put(T&& x) //const T &&x 左值常因用,编译器认为不可变,变成具名变量
{
Add(std::forward<T>(x)); //保证x为右值
}//可接收一切类型
void Take(std::list<T>& list)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
if (m_needStop)
{
return;
}
list = std::move(m_queue); //取走全部任务
m_notFull.notify_one(); //唤醒添加任务
}
void Take(T& t)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
if (m_needStop)
{
return;
}
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
void Stop()
{
{
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();
}
bool Full()const
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size() = m_max_Size;
}
size_t Size()
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size();
}
private:
bool NotFull()const
{
bool full = m_queue.size() >= m_max_Size;
if (full)
{
cout << "缓冲区已经满了 m_queue full!" << endl;
}
return !full;
}
bool NotEmpty()const
{
bool empty = m_queue.empty();
if (empty)
{
cout << "m_queue empty!" << endl;
}
return !empty;
}
template<class F>
void Add(F&& x) //接收任意类型 并保持值状态
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notFull.wait(locker, [this]()->bool {return m_needStop || NotFull(); });
m_queue.push_back(std::forward<F>(x)); //入队
m_notEmpty.notify_one();
}
private:
std::list<T> m_queue;
mutable std::mutex m_mutex;
std::condition_variable m_notEmpty; //取事务等待队列
std::condition_variable m_notFull; //添加等待队列
int m_max_Size; //同步队列max
bool m_needStop; //是否停止
};
异步服务层
const int MaxTaskCount = 100;
class ThreadPool
{
public:
using Task = std::function<void()>; //返回类型为空 无参
ThreadPool(int numThreads = std::thread::hardware_concurrency()) //返回逻辑核数量
:m_queue(MaxTaskCount)
{
Start(numThreads);
}
void Stop()
{
std::call_once(m_flag, [this] {StopThreadGroup(); });//终止所有线程
}
private:
void Start(int numThreads)
{
m_running = true; //叫停线程
for (int i = 0; i < numThreads; ++i)
{
m_threadgroup.push_back(std::make_shared<thread>(&ThreadPool::RunInThrea,this));
// & 告诉系统为类型成员,而不是静态成员
}
}
void RunInThrea()
{
while (m_running)
{
std::list<Task> list;
m_queue.Take(list); //取一批事务
for (auto& task : list)
{
if (!m_running)
{
return;
}
task(); //处理事务
}
}
}
void StopThreadGroup() //停止线程组线程
{
m_queue.Stop();
m_running = false;
for (auto& th : m_threadgroup)
{
if (th) //智能指针
{
th->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; //标记 只执行一次
};
测试代码
template<typename T>
class SyncQueue
{
public:
SyncQueue(int maxSize) :m_max_Size(maxSize), m_needStop(false)
{}
void Put(const T& x)
{
Add(x);
}
void Put(T&& x) //const T &&x 左值常因用,编译器认为不可变,变成具名变量
{
Add(std::forward<T>(x)); //保证x为右值
}//可接收一切类型
void Take(std::list<T>& list)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); });
if (m_needStop)
{
return;
}
list = std::move(m_queue); //取走全部任务
m_notFull.notify_one(); //唤醒添加任务
}
void Take(T& t)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this]()->bool {return m_needStop || NotEmpty(); }); //空队列阻塞 不空继续运行
if (m_needStop)
{
return;
}
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
void Stop()
{
{
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();
}
bool Full()const
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size() = m_max_Size;
}
size_t Size()
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size();
}
private:
bool NotFull()const
{
bool full = m_queue.size() >= m_max_Size;
if (full)
{
cout << "缓冲区已经满了 m_queue full!" << endl;
}
return !full;
}
bool NotEmpty()const
{
bool empty = m_queue.empty();
if (empty)
{
cout << "m_queue empty!" << endl;
}
return !empty;
}
template<class F>
void Add(F&& x) //接收任意类型 并保持值状态
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notFull.wait(locker, [this]()->bool {return m_needStop || NotFull(); });
if (m_needStop)
{
return;
}
m_queue.push_back(std::forward<F>(x)); //入队
m_notEmpty.notify_one();
}
private:
std::list<T> m_queue;
mutable std::mutex m_mutex;
std::condition_variable m_notEmpty; //取事务等待队列
std::condition_variable m_notFull; //添加等待队列
int m_max_Size; //同步队列max
bool m_needStop; //是否停止
};
const int MaxTaskCount = 10;
class ThreadPool
{
public:
using Task = std::function<void()>; //返回类型为空 无参
ThreadPool(int numThreads = std::thread::hardware_concurrency()) //返回逻辑核数量
:m_queue(MaxTaskCount)
{
//Start(numThreads);
}
~ThreadPool()
{
Stop();
}
void Stop()
{
std::call_once(m_flag, [this] {StopThreadGroup(); });//终止所有线程
}
void AddTask(Task&& task)
{
m_queue.Put(task); //添加事务
}
void AddTask(const Task& task)
{
m_queue.Put(task); //添加事务
}
void Start(int numThreads)
{
m_running = true; //叫停线程
for (int i = 0; i < numThreads; ++i)
{
m_threadgroup.push_back(std::make_shared<thread>(&ThreadPool::RunInThrea, this));
// & 告诉系统为类型成员,而不是静态成员
}
}
private:
void RunInThrea()
{
while (m_running)
{
std::list<Task> list;
m_queue.Take(list); //取一批事务
for (auto& task : list)
{
if (!m_running)
{
return;
}
task(); //处理事务
}
}
}
void StopThreadGroup() //停止线程组线程
{
m_queue.Stop();
m_running = false;
for (auto& th : m_threadgroup)
{
if (th) //智能指针
{
th->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* alloc(size_t sz)
{
void* s = malloc(sz);
return s;
}
void f()
{
cout << "f" << endl;
}
void func(ThreadPool& pool)
{
cout << "void funa" << endl;
for (int i = 0; i < 100; ++i)
{
auto thdid = this_thread::get_id();
pool.AddTask(f); //需要添加返回类型空 参数空的事务
}
}
void TestThdPool()
{
ThreadPool pool;
std::thread tha(func, std::ref(pool)); //添加事务
std::thread thb(func, std::ref(pool));
std::this_thread::sleep_for(std::chrono::seconds(5));
pool.Start(8);
tha.join();
}
int main()
{
TestThdPool();
return 0;
}
尽管这一步可以成功的运行,但是还是确实一部分,如何对事务的参数的接收以及对返回类型的接收