使用C++11 开发一个半同步半异步线程池
摘自:《深入应用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 开发一个半同步半异步线程池的更多相关文章
- 使用C++11实现一个半同步半异步线程池
前言 C++11之前我们使用线程需要系统提供API.posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex.std ...
- c++11 实现半同步半异步线程池
感受: 随着深入学习,现代c++给我带来越来越多的惊喜- c++真的变强大了. 半同步半异步线程池: 事实上非常好理解.分为三层 同步层:通过IO复用或者其它多线程多进程等不断的将待处理事件加入到队列 ...
- 分布式缓存系统 Memcached 半同步/半异步模式
在前面工作线程初始化的分析中讲到Memcached采用典型的Master_Worker模式,也即半同步/半异步的高效网络并发模式.其中主线程(异步线程)负责接收客户端连接,然后分发给工作线程,具体由工 ...
- 领导者/追随者(Leader/Followers)模型和半同步/半异步(half-sync/half-async)模型都是常用的客户-服务器编程模型
领导者-追随者(Leader/Followers)模型的比喻 半同步/半异步模型和领导者/追随者模型的区别: 半同步/半异步模型拥有一个显式的待处理事件队列,而领导者-追随者模型没有一个显式的队列(很 ...
- 半同步半异步模式的实现 - MSMQ实现
半同步半异步模式的实现 - MSMQ实现 所谓半同步半异步是指,在某个方法调用中,有些代码行是同步执行方式,有些代码行是异步执行方式,下面我们来举个例子,还是以经典的PlaceOrder来说,哈哈. ...
- (原创)C++半同步半异步线程池2
(原创)C++半同步半异步线程池 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 线程池可以高效的处理任务,线程池中开启多个线程,等待同步队列中的任务到来,任务到来多个线程 ...
- 【Networking】(转)一个非常好的epoll+线程池服务器Demo
(转)一个非常好的epoll+线程池服务器Demo Reply 转载自:http://zhangyafeikimi.javaeye.com/blog/285193 [cpp] /** 张亚霏修改 文件 ...
- django学习-11.开发一个简单的醉得意菜单和人均支付金额查询页面
1.前言 刚好最近跟技术部门的[产品人员+UI人员+测试人员],组成了一桌可以去公司楼下醉得意餐厅吃饭的小team. 所以为了实现这些主要点餐功能: 提高每天中午点餐效率,把点餐时间由20分钟优化为1 ...
- Half Sync And Half Async 半同步半异步模式
如题,这是一个典型的CS结构的模式,至少曾经在CS结构中用过,只是没用好.当年用UDP死活都处理不过来网络命令,用此模式轻松解决. 此模式是典型的三层架构,同步层在一个线程内处理业务逻辑:异步层接受并 ...
随机推荐
- ajax +LoadLayer插件实现访问页面跳转loading..
布局页:第一步进行扩展ajax$(function () { $.ajax2 = function (options) {//遮罩 Mask();//jquery 原生ajax $.ajax(opti ...
- [Oracle]Oracle数据库CPU利用率很高解决方案
Oracle数据库经常会遇到CPU利用率很高的情况,这种时候大都是数据库中存在着严重性能低下的SQL语句,这种SQL语句大大的消耗了CPU资源,导致整个系统性能低下.当然,引起严重性能低下的SQL语句 ...
- C#基础笔记(第二十天)
1.复习属性:保护字段的构造函数:初始化对象初始化对象:给对象的每个属性去赋值什么时候会调用构造函数:当我们new的时候面向对象中需要注意的两个关键字this 1.代表当前类的对象 2.调用自己的构造 ...
- ubuntu emacs的安装
在终端依次输入这三条命令即可 sudo add-apt-repository ppa:ubuntu-elisp/ppa sudo apt-get update sudo apt-get install ...
- soundPool的使用
SoundPool soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100); HashMap<Integer, Integer& ...
- CPU缓存刷新的误解
即使是资深的技术人员,我经常听到他们谈论某些操作是如何导致一个CPU缓存的刷新.看来这是关于CPU缓存如何工作和缓存子系统如何与执行核心交互的一个常见误区.本文将致力于解释CPU缓存的功能以及执行程序 ...
- php性能优化二(PHP配置php.ini)
PHP优化对于PHP的优化主要是对php.ini中的相关主要参数进行合理调整和设置,以下我们就来看看php.ini中的一些对性能影响较大的参数应该如何设置. # vi /etc/PHP.ini (1) ...
- mxonline实战4,用户登陆页面2和用户注册1
一. 基于类来定义view.py diango中使用基于类来定义views的功能,其实更加方便,因为这样可继承一些定义好的基类,来减少我们的代码量 1. 使用基于类的方法,来重新定 ...
- 架构师养成记--33.Redis哨兵、redis简单事务
Redis哨兵 有了主从复制,如果我想想对主从服务器进行监控,在redis2.6后提供了哨兵机制,2.6有哨兵1.0版本,并不稳定.2.8以后的哨兵功能才稳定起来. 顾名思义,哨兵就是监控Redis系 ...
- SDN定义网络
http://edu.51cto.com/course/course_id-4466.html http://edu.51cto.com/course/course_id-4497.html