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个问题
引言 在日常开发中,线程池是使用非常频繁的一种技术,无论是服务端多线程接收用户请求,还是客户端多线程处理数据,都会用到线程池技术,那么全面的了解线程池的使用.背后的实现原理以及合理的优化线程池的大小等 ...
随机推荐
- 忽略git中不需要进行版本管理的文件
在git中我们提交项目的时候有很多东西是不需要进行版本管理的,因此我们需要忽略掉. 虽然在github2.0的windows客户端提供了工具,但是这个工具并不是想象中的那么好用. 在上面点右键出现的D ...
- Android/Linux boot time优化
基于analyze_boot.py分析Android/Linux的kernel boot时间 1.修改HiKey的BoardConfig.mk文件,使能initcall_debug,增加dmesg b ...
- 递归生成树对象,应用于Easyui,Tree控件
1.生成树节点对象 /// <summary> /// 生成树的节点 /// </summary> public class TreeNode { public TreeNod ...
- JobDeer 的《程序员必读的职业规划书》
JobDeer 的<程序员必读的职业规划书> 关键字 持续性,人生规划,职业规划 概念 职业规划三部分: 职业定位 目标设定 通道设计 职业价值论: 能为公司做什么 同样的能力再不同公司价 ...
- 在PHP中开启CURL扩展,使其支持curl()函数
在用PHP开发CMS的时候,要用到PHP的curl函数,默认状态下,这个函数需要开启CURL扩展,有主机使用权的,可通过PHP.ini文件开启本扩展,方法如下: 1.打开php.ini,定位到;ext ...
- windows下配置lamp环境(3)---配置PHP5.4
下面配置php Php文件夹里有两个php.ini-*文件,随便修改一个,去掉后缀,变成php.ini (如图) 打开php.ini ,添加php扩展目录723行左右(其实放哪都无所谓,只不过php. ...
- Harris Corner(Harris角检测)
在做图像匹配时,常需要对两幅图像中的特征点进行匹配.为了保证匹配的准确性,所选择的特征必须有其独特性,角点可以作为一种不错的特征. 那么为什么角点有其独特性呢?角点往往是两条边缘的交点,它是两条边缘方 ...
- Retrofit2.0+OkHttp打印Request URL(请求地址参数)
学习了Retrofit中的拦截器功能:实现日志中打印请求头内容 Retrofit 2+ 是基于OKHttp进行封装的,那么也就是说想进行请求拦截然后进行打印出来的话,就必须要从OkHttp进行入手. ...
- epoll函数及三种I/O复用函数的对比
epoll函数 #include <sys/epoll.h>int epoll_create(int size)int epoll_ctl(int epfd, int op, int fd ...
- android slidingview
http://blog.csdn.net/sky181772733/article/details/6969810 http://blog.csdn.net/ithomer/article/detai ...