摘自:《深入应用C++11》第九章

实际中,主要有两种方法处理大量的并发任务,一种是一个请求由系统产生一个相应的处理请求的线程(一对一)

另外一种是系统预先生成一些用于处理请求的进程,当请求的任务来临时,先放入同步队列中,分配一个处理请求的进程去处理任务,

线程处理完任务后还可以重用,不会销毁,而是等待下次任务的到来。(一对多的线程池技术)

线程池技术,能避免大量线程的创建和销毁动作,节省资源,对于多核处理器,由于线程被分派配到多个cpu,会提高并行处理的效率。

线程池技术分为半同步半异步线程池和领导者追随者线程池,下面附上代码:

//SyncQueue.hpp
//同步队列,存放任务
#ifndef SYNCQUEUE_HPP
#define SYNCQUEUE_HPP #include <list>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <utility>
#include <iostream> template<typename T>
class SyncQueue
{
public:
SyncQueue(int maxSize) : m_maxSize(maxSize),m_needStop(false){} void Put(const T& x)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notFull.wait(locker,[this]{ return m_needStop || NotFull();});
if(m_needStop)
return;
m_queue.push_back(x);
m_notEmpty.notify_one();
} void Take(std::list<T>& list)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker,[this]{return m_needStop || NotEmpty();});
if(m_needStop) list = std::move(m_queue); //move semantics,avoid copy.
m_notFull.notify_one();
} void Take(T& x)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker,[this]{return m_needStop || NotEmpty();});
if(m_needStop)
return;
x=m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
} void Stop()
{
{
std::lock_guard<std::mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
} std::size_t Size()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
}
private:
bool NotFull()
{
bool full = m_queue.size() >= m_maxSize;
if(full)
std::cout << "the buffer is full,waiting...\n";
return !full;
}
bool NotEmpty()
{
bool empty = m_queue.empty();
if(empty)
std::cout << "the buffer is empty,waiting...\n";
return !empty;
}
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; //stop flag
}; #endif // SYNC_QUEUE_HPP
//ThreadPool.hpp

#ifndef THREAD_POOL_HPP
#define THREAD_POOL_HPP #include <list>
#include <thread>
#include <memory>
#include "SyncQueue.hpp"
#include <functional>
#include <atomic> const int MaxTaskCount = ; class ThreadPool
{
public:
using Task = std::function<void()>; ThreadPool(int numThreads) :
m_taskQueue(MaxTaskCount)
{
Start(numThreads);
} ~ThreadPool(){ Stop();};
void Stop()
{
std::call_once(m_once_flag,[this]{StopThreadGroup();});
} void AddTask(const Task& task)
{
m_taskQueue.Put(task);
} std::size_t SyncQueueSize()
{
return m_taskQueue.Size();
}
private:
void Start(int numThreads)
{
m_running = true; for(int i = ;i < numThreads;++i)
{
m_threadGrop.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread,this));
} } void RunInThread()
{
while(m_running)
{
std::list<Task> list;
m_taskQueue.Take(list);
for(auto& task : list)
{
if(!m_running)
return; task();
}
}
return;
} void StopThreadGroup()
{
m_taskQueue.Stop();
m_running = false;
for(auto thread : m_threadGrop)
{
if(thread)
thread->join();
}
m_threadGrop.clear();
}
private:
std::list<std::shared_ptr<std::thread>> m_threadGrop; //thread group
SyncQueue<Task> m_taskQueue;
std::atomic_bool m_running;
std::once_flag m_once_flag;
}; #endif // THREAD_POOL_HPP

测试:

#include "ThreadPool.hpp"
#include <thread>
#include <iostream>
#include <chrono>
#include <functional>
int main()
{
ThreadPool pool(); //create two threads to handle tasks std::thread thd1([&pool]{
for(int i = ;i < ;i++)
{
auto thdId = std::this_thread::get_id(); pool.AddTask([thdId]{
std::cout<<"thdID1: "<< thdId << std::endl;
});
}
}); std::thread thd2([&pool]{
for(int i = ;i < ;i++)
{
auto thdID = std::this_thread::get_id(); pool.AddTask([thdID]{
std::cout << "thdID2: " << thdID << std::endl;
});
}
}); thd1.join();
thd2.join();
std::this_thread::sleep_for(std::chrono::seconds());
pool.Stop();
return ;
}

使用C++11 开发一个半同步半异步线程池的更多相关文章

  1. 使用C++11实现一个半同步半异步线程池

    前言 C++11之前我们使用线程需要系统提供API.posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex.std ...

  2. c++11 实现半同步半异步线程池

    感受: 随着深入学习,现代c++给我带来越来越多的惊喜- c++真的变强大了. 半同步半异步线程池: 事实上非常好理解.分为三层 同步层:通过IO复用或者其它多线程多进程等不断的将待处理事件加入到队列 ...

  3. 分布式缓存系统 Memcached 半同步/半异步模式

    在前面工作线程初始化的分析中讲到Memcached采用典型的Master_Worker模式,也即半同步/半异步的高效网络并发模式.其中主线程(异步线程)负责接收客户端连接,然后分发给工作线程,具体由工 ...

  4. 领导者/追随者(Leader/Followers)模型和半同步/半异步(half-sync/half-async)模型都是常用的客户-服务器编程模型

    领导者-追随者(Leader/Followers)模型的比喻 半同步/半异步模型和领导者/追随者模型的区别: 半同步/半异步模型拥有一个显式的待处理事件队列,而领导者-追随者模型没有一个显式的队列(很 ...

  5. 半同步半异步模式的实现 - MSMQ实现

    半同步半异步模式的实现 - MSMQ实现 所谓半同步半异步是指,在某个方法调用中,有些代码行是同步执行方式,有些代码行是异步执行方式,下面我们来举个例子,还是以经典的PlaceOrder来说,哈哈. ...

  6. (原创)C++半同步半异步线程池2

    (原创)C++半同步半异步线程池 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 线程池可以高效的处理任务,线程池中开启多个线程,等待同步队列中的任务到来,任务到来多个线程 ...

  7. 【Networking】(转)一个非常好的epoll+线程池服务器Demo

    (转)一个非常好的epoll+线程池服务器Demo Reply 转载自:http://zhangyafeikimi.javaeye.com/blog/285193 [cpp] /** 张亚霏修改 文件 ...

  8. django学习-11.开发一个简单的醉得意菜单和人均支付金额查询页面

    1.前言 刚好最近跟技术部门的[产品人员+UI人员+测试人员],组成了一桌可以去公司楼下醉得意餐厅吃饭的小team. 所以为了实现这些主要点餐功能: 提高每天中午点餐效率,把点餐时间由20分钟优化为1 ...

  9. Half Sync And Half Async 半同步半异步模式

    如题,这是一个典型的CS结构的模式,至少曾经在CS结构中用过,只是没用好.当年用UDP死活都处理不过来网络命令,用此模式轻松解决. 此模式是典型的三层架构,同步层在一个线程内处理业务逻辑:异步层接受并 ...

随机推荐

  1. 作业一:博客和Github简单练习

    (1)自我介绍 Hello everybody! 我叫纪杨阳,学号1413042002,网络工程141班. 本人没啥特殊的兴趣爱好,都是些平常得不能再平常的吃吃睡睡.要说感兴趣的,可能就是音乐和服饰还 ...

  2. 基于Extjs的web表单设计器 第三节——控件拖放

    看过之前设计器截图的朋友应该有印象,可能会发觉我们的设计器UI设计布局其实类似Visual studio 的设计界面,采用的是左.中.右三个区域布局.左侧为控件区域.中间为表单的画布设区域.右侧为属性 ...

  3. 在SharePoint列表中使用动态筛选条件[今日][Today]

    如果在SharePoint使用了日历控件或者其他列表中有时间字段,用户经常希望能够动态使用条件字段进行筛选,例如希望筛选出开始日期是今天的事件.未来三日的事件. SharePoint的列表筛选条件支持 ...

  4. Tomcat启动报错Invalid character found in method name. HTTP method names must be tokens

    1.tomcat服务器需配置三个端口才能启动,安装时默认启用了这三个端口,当要运行多个tomcat服务时需要修改这三个端口,不能相同. 端口一: 修改http访问端口(默认为8080端口),配置文件为 ...

  5. 10-11Linux用户管理规则及用户管理函数

    用户管理: useradd, userdel, usermod, passwd, chsh, chfn, finger, id, chage 组管理: groupadd, groupdel, grou ...

  6. SQL表连接查询inner join left join right join full join ...

    一.最常见的连接查询 select  s.name,m.mark from student s,mark m  where s.id=m.studentid. 二.内连接-inner join sel ...

  7. SQL Server中将多行数据拼接为一行数据并且有特殊字符

    有表结构如下: 这时,要求显示所有学生的爱好的结果集,代码如下: ) as hobby FROM ( SELECT name, (SELECT hobby+',' FROM student WHERE ...

  8. 数据与任务的并行---Parallel类

    Parallel类是对线程的抽象,提供数据与任务的并行性.类定义了静态方法For和ForEach,使用多个任务来完成多个作业.Parallel.For和Parallel.ForEach方法在每次迭代的 ...

  9. [POJ-3237] [Problem E]

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 13156   Accepted: 3358 题目链接 http: ...

  10. angular核心原理解析2:注入器的创建和使用

    上一课没有讲到创建注入器的方法createInjector. 此方法,会创建两种不同的注入器:第一种叫做providerInjector,第二种叫做instanceInjector.providerI ...