C++11下的线程池以及灵活的functional + bind + lamda
利用boost的thread实现一个线程类,维护一个任务队列,以便可以承载非常灵活的调用。这个线程类可以方便的为后面的线程池打好基础。线程池还是动态均衡,没有什么别的。由于minGW 4.7 对 C++11 thread 不支持,所以采用 boost 代替,linux 下是支持的,只是名字空间不同而已,套路都一样。先上代码: [cpp] view plaincopy #include #include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include #include #include #include #include #include #include #include //This class defines a class contains a thread, a task queue class cpp11_thread { public: cpp11_thread() :m_b_is_finish(false) ,m_pthread(nullptr) { } ~cpp11_thread() { if (m_pthread != nullptr) delete m_pthread; m_list_tasks.clear(); } public: //wait until this thread is terminated; void join() { terminate(); if (m_pthread!=nullptr) m_pthread->join(); } //wait until this thread has no tasks pending. void wait_for_idle() { while(load()) boost::this_thread::sleep(boost::posix_time::milliseconds(200)); } //set the mask to termminiate void terminate() {m_b_is_finish = true; m_cond_incoming_task.notify_one();} //return the current load of this thread size_t load() { size_t sz = 0; m_list_tasks_mutex.lock(); sz = m_list_tasks.size(); m_list_tasks_mutex.unlock(); return sz; } //Append a task to do size_t append(std::function< void (void) > func) { if (m_pthread==nullptr) m_pthread = new boost::thread(std::bind(&cpp11_thread::run,this)); size_t sz = 0; m_list_tasks_mutex.lock(); m_list_tasks.push_back(func); sz = m_list_tasks.size(); //if there were no tasks before, we should notidy the thread to do next job. if (sz==1) m_cond_incoming_task.notify_one(); m_list_tasks_mutex.unlock(); return sz; } protected: std::atomic< bool> m_b_is_finish; //atomic bool var to mark the thread the next loop will be terminated. std::list<std::function< void (void)> > m_list_tasks; //The Task List contains function objects boost::mutex m_list_tasks_mutex; //The mutex with which we protect task list boost::thread *m_pthread; //inside the thread, a task queue will be maintained. boost::mutex m_cond_mutex; //condition mutex used by m_cond_locker boost::condition_variable m_cond_incoming_task; //condition var with which we notify the thread for incoming tasks protected: void run() { // loop wait while (!m_b_is_finish) { std::function< void (void)> curr_task ; bool bHasTasks = false; m_list_tasks_mutex.lock(); if (m_list_tasks.empty()==false) { bHasTasks = true; curr_task = *m_list_tasks.begin(); } m_list_tasks_mutex.unlock(); //doing task if (bHasTasks) { curr_task(); m_list_tasks_mutex.lock(); m_list_tasks.pop_front(); m_list_tasks_mutex.unlock(); } if (!load()) { boost::unique_lock< boost::mutex> m_cond_locker(m_cond_mutex); boost::system_time const timeout=boost::get_system_time()+ boost::posix_time::milliseconds(5000); if (m_cond_locker.mutex()) m_cond_incoming_task.timed_wait(m_cond_locker,timeout);//m_cond_incoming_task.wait(m_cond_locker); } } } }; //the thread pool class class cpp11_thread_pool { public: cpp11_thread_pool(int nThreads) :m_n_threads(nThreads) { assert(nThreads>0 && nThreads<=512); for (int i = 0; i< nThreads ;i++) m_vec_threads.push_back(std::shared_ptr<cpp11_thread>(new cpp11_thread())); } ~cpp11_thread_pool() { } public: //total threads; size_t count(){return m_vec_threads.size();} //wait until all threads is terminated; void join() { for_each(m_vec_threads.begin(),m_vec_threads.end(),[this](std::shared_ptr<cpp11_thread> & item) { item->terminate(); item->join(); }); } //wait until this thread has no tasks pending. void wait_for_idle() { int n_tasks = 0; do { if (n_tasks) boost::this_thread::sleep(boost::posix_time::milliseconds(200)); n_tasks = 0; for_each(m_vec_threads.begin(),m_vec_threads.end(),[this,&n_tasks](std::shared_ptr<cpp11_thread> & item) { n_tasks += item->load(); }); }while (n_tasks); } //set the mask to termminiate void terminate() { for_each(m_vec_threads.begin(),m_vec_threads.end(),[this](std::shared_ptr<cpp11_thread> & item) { item->terminate(); }); } //return the current load of this thread size_t load(int n) { return (n>=m_vec_threads.size())?0:m_vec_threads[n]->load(); } //Append a task to do void append(std::function< void (void) > func) { int nIdx = -1; unsigned int nMinLoad = -1; for (unsigned int i=0;i<m_n_threads;i++) { if (nMinLoad> m_vec_threads[i]->load()) { nMinLoad = m_vec_threads[i]->load(); nIdx = i; } } assert(nIdx>=0 && nIdx<m_n_threads); m_vec_threads[nIdx]->append(func); } protected: //NO. threads int m_n_threads; //vector contains all the threads std::vector<std::shared_ptr<cpp11_thread> > m_vec_threads; }; //a function which will be executed in sub thread. void hello() { //sleep for a while boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%900+100)); std::cout << "Hello world, I'm a function runing in a thread!" << std::endl; } //a class has a method, which will be called in a thread different from the main thread. class A { private: int m_n; public: A(int n) :m_n(n) {} ~A(){} public: void foo (int k) { //sleep for a while boost::this_thread::sleep(boost::posix_time::milliseconds(rand()%900+100)); std::cout <<"n*k = "<<k*m_n<<std::endl; m_n++; } }; //let's test the thread. int main() { cpp11_thread_pool thread(2); srand((unsigned int)time(0)); A a(1),b(2),c(3); int nsleep = rand()%900+100; //append a simple function task thread.append(&hello); //append lamda thread.append ( [&nsleep]() { boost::this_thread::sleep(boost::posix_time::milliseconds(nsleep)); std::cout<<"I'm a lamda runing in a thread"<<std::endl; } ); //append object method with copy-constructor(value-assignment) thread.append(std::bind(&A::foo,a,10)); thread.append(std::bind(&A::foo,b,11)); thread.append(std::bind(&A::foo,c,12)); thread.append(std::bind(&A::foo,a,100)); //append object method with address assignment, will cause the objects' member increase. thread.append(std::bind(&A::foo,&a,10)); thread.append(std::bind(&A::foo,&b,11)); thread.append(std::bind(&A::foo,&c,12)); thread.append(std::bind(&A::foo,&a,100)); //wait for all tasks done. thread.wait_for_idle(); //kill thread.terminate(); //wait for killed thread.join(); //test function std::function < void (void) > func1 = &hello; std::function < void (void) > func2 = &hello; if (func1.target()!=func2.target()) return 0; else return 1; } 程序输出: [plain] view plaincopy Hello world, I'm a function runing in a thread! I'm a lamda runing in a thread n*k = 22 n*k = 10 n*k = 36 n*k = 100 n*k = 22 n*k = 10 n*k = 36 n*k = 200 Process returned 0 (0x0) execution time : 2.891 s Press any key to continue. 下面来看看代码。首先是线程类。 第13-99行是线程类。该类实现了一个带任务队列的线程模型。关键部件是62行的std::list<std::function< void (void)> > m_list_tasks; ,这个fifo 用来承载顺序在子线程运行的任务。任务通过48行的append方法进行追加,64行m_list_tasks_mutex是一个mutex,来保护队列的进出。65行定义的线程对象boost::thread在构造函数中初始化并运行,绑定了本对象的run方法。线程得以运行的关键是run方法,在71-99行定义。该方法首先判断是否有pending的任务,有的话就弹出来执行。如果任务做完了,则使用67行定义的条件变量m_cond_incoming_task 进行wait, 直到新的任务到来,在第56行触发条件,激活队列。 线程类还提供了一些方法,比如load()返回队列的大小,以及terminate终止线程。而后,转到线程池。线程池采用最简单的策略,即直接分配给最空闲的线程。 有了上述封装,main函数就简单多了。可以append几乎所有的东西到线程池,这是以前简单的利用 virtual function 很难做到的。
C++11下的线程池以及灵活的functional + bind + lamda的更多相关文章
- 第11章 Windows线程池(3)_私有的线程池
11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...
- 第11章 Windows线程池(1)_传统的Windows线程池
第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...
- [C++]C风格、C++风格和C++11特性的线程池
线程池概念 假设完成一项任务需要的时间=创建线程时间T1+线程执行任务时间T2+销毁线程时间T3,如果T1+T3的时间远大于T2,通常就可以考虑采取线程池来提高服务器的性能 thread pool就是 ...
- C++11的简单线程池代码阅读
这是一个简单的C++11实现的线程池,代码很简单. 原理就是管理一个任务队列和一个工作线程队列. 工作线程不断的从任务队列取任务,然后执行.如果没有任务就等待新任务的到来.添加新任务的时候先添加到任务 ...
- 基于无锁队列和c++11的高性能线程池
基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上 标签: <无> 代码片段(6)[ ...
- Windows核心编程:第11章 Windows线程池
Github https://github.com/gongluck/Windows-Core-Program.git //第11章 Windows线程池.cpp: 定义应用程序的入口点. // #i ...
- 使用C++11 实现的线程池
最近打算做一个服务器端程序,每来一个客户端请求新开一个线程进行处理.在网上查了一些资料后,准备使用线程池来做这个东西.使用C++11新的库处理想线程问题比以前简单了许多,在网上找到一份线程池的实现,h ...
- Linux下简单线程池的实现
大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个服务请求到达,就创建一个新的服务 ...
- Java并发(11)- 有关线程池的10个问题
引言 在日常开发中,线程池是使用非常频繁的一种技术,无论是服务端多线程接收用户请求,还是客户端多线程处理数据,都会用到线程池技术,那么全面的了解线程池的使用.背后的实现原理以及合理的优化线程池的大小等 ...
随机推荐
- NS2仿真:使用NS仿真软件模拟简单网络模型
NS2仿真实验报告1 实验名称:使用NS仿真软件模拟简单网络模型 实验日期:2015年3月2日~2015年3月7日 实验报告日期:2015年3月8日 一.实验环境(网络平台,操作系统,网络拓扑图) 运 ...
- thinkphp 中 使用七牛云上传
利用七牛云私有空间存储文件 第一步,注册七牛云,创建空间,将空间设为私有 需要记下的东西: AK,SK,bucket 第二步配置ThinkPHP 在config.php添加 'UPLOAD_SITEI ...
- DataGrid( 数据表格) 组件[1]
本节课重点了解 EasyUI 中 DataGrid(数据表格)组件的使用方法,这个组件依赖于Panel(面板).Resizeable(调整大小).LinkButton(按钮).Pageination( ...
- 规约模式(Specification Pattern)
前期准备之规约模式(Specification Pattern) 一.前言 在专题二中已经应用DDD和SOA的思想简单构建了一个网上书店的网站,接下来的专题中将会对该网站补充更多的DDD的内容.本专题 ...
- Mysql的Error 1364
在安装mysql 5.5.8的最后一步,应用安全配置时, 弹出错误对话框, Error Nr.1364 authentication_string 解决办法: 1.暂时不要关闭该窗口,cmd命令,执行 ...
- java下tcp的socket连接
serverDemo package cn.stat.p4.ipdemo; import java.io.IOException; import java.io.InputStream; import ...
- 打破C++ Const 的规则
从一个C++菜鸟改函数开始 CString MyClass::GetStringValue() const { return m_strValue; } 这个值可能还没有赋值,好吧,那么我先判断是不是 ...
- POJ 模拟题集合
http://www.cppblog.com/Uriel/articles/101592.html 感觉这个暑假没有去年有激情啊,,,还没到状态就已经块上学了,,, 真是弱暴了,,,找几道模拟题刷刷. ...
- ThinkPHP内置函数详解D、F、S、C、L、A、I
单字母函数D.F.S.C.L.A.I 他们都在ThinkPHP核心的ThinkPHP/Mode/Api/functions.php这个文件中定义. 下面我分别说明一下他们的功能: D() 加载Mode ...
- [Flask Security]当不能通过认证的时候制定跳转
Flask Security这个插件能对用户权限进行很好的控制. 通过三个model实现: User,存放用户数据 Role,存放角色数据 User_Role.存放用户角色信息 user_datast ...