摘自:《深入应用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. 安装TestNG在eclipse中的插件

    两种方法可以安装TestNG Eclipse插件: 第一种,离线安装 TestNG Eclipse插件下载地址http://testng.org/doc/download.html. 下载下来以后,放 ...

  2. 使用python登录CNZZ访问量统计网站,然后获取相应的数据

    思路: 第一步:使用pypeteer.launcher打开浏览器, 第二步:向CNZZ的登录(通过使用iframe嵌入的阿里巴巴单点登录页面),向iframe页面中自动输入用户名和密码,然后点击登录按 ...

  3. 修改TFS附件大小的限制

    在TFS服务器使用浏览器上打开如下地址:http://localhost:8080/tfs/<CollectionName>/WorkItemTracking/v1.0/Configura ...

  4. svn: Can't convert string from 'UTF-8' to native encoding: 解决办法

    在linux中,svn co 或 svn up 时有中文文件名的文件的话,可能会报下面的错: [root@linkea-dev-srv1 ~]# svn upsvn: Can't convert st ...

  5. asp.net core部署到iis

    asp.net core项目部署到IIS稍微不同于之前,记录几个要点: 一.下载安装.NET Core 托管捆绑包,下载地址,这个链接或许不是最新的了,官方文档里面有这个链接,到下图所示位置即可找到. ...

  6. C#发送邮件及注意事项

    //参数配置 static readonly string smtpServer = System.Configuration.ConfigurationManager.AppSettings[&qu ...

  7. C# 依赖注入 & MEF

    之前面试有问道依赖注入,因为一直是做客户端的发开发,没有接触这个,后边工作接触到了MEF,顺便熟悉一下依赖注入 详细的概念解释就不讲了,网上一大把,个人觉着依赖注入本质是为了解耦,方便扩展 依赖注入的 ...

  8. 黄包车比赛 python学习

    将性别进行编码: https://github.com/Bifzivkar/Boutique-Travel-Services-Predict/blob/master/feature/2_feature ...

  9. KindEditor的使用

    KindEditor 是一套开源的在线HTML编辑器,主要用于让用户在网站上获得所见即所得编辑效果,开发人员可以用 KindEditor 把传统的多行文本输入框(textarea)替换为可视化的富文本 ...

  10. django入门-静态文件-part6

    尊重作者的劳动,转载请注明作者及原文地址 http://www.cnblogs.com/txwsqk/p/6517553.html 完全翻译自官方文档 https://docs.djangoproje ...