利用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的更多相关文章

  1. 第11章 Windows线程池(3)_私有的线程池

    11.3 私有的线程池 11.3.1 创建和销毁私有的线程池 (1)进程默认线程池 当调用CreateThreadpoolwork.CreateThreadpoolTimer.CreateThread ...

  2. 第11章 Windows线程池(1)_传统的Windows线程池

    第11章 Windows线程池 11.1 传统的Windows线程池及API (1)线程池中的几种底层线程 ①可变数量的长任务线程:WT_EXECUTELONGFUNCTION ②Timer线程:调用 ...

  3. [C++]C风格、C++风格和C++11特性的线程池

    线程池概念 假设完成一项任务需要的时间=创建线程时间T1+线程执行任务时间T2+销毁线程时间T3,如果T1+T3的时间远大于T2,通常就可以考虑采取线程池来提高服务器的性能 thread pool就是 ...

  4. C++11的简单线程池代码阅读

    这是一个简单的C++11实现的线程池,代码很简单. 原理就是管理一个任务队列和一个工作线程队列. 工作线程不断的从任务队列取任务,然后执行.如果没有任务就等待新任务的到来.添加新任务的时候先添加到任务 ...

  5. 基于无锁队列和c++11的高性能线程池

    基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上   标签: <无>   代码片段(6)[ ...

  6. Windows核心编程:第11章 Windows线程池

    Github https://github.com/gongluck/Windows-Core-Program.git //第11章 Windows线程池.cpp: 定义应用程序的入口点. // #i ...

  7. 使用C++11 实现的线程池

    最近打算做一个服务器端程序,每来一个客户端请求新开一个线程进行处理.在网上查了一些资料后,准备使用线程池来做这个东西.使用C++11新的库处理想线程问题比以前简单了许多,在网上找到一份线程池的实现,h ...

  8. Linux下简单线程池的实现

    大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的.在传统的多线程服务器模型中是这样实现的:一旦有个服务请求到达,就创建一个新的服务 ...

  9. Java并发(11)- 有关线程池的10个问题

    引言 在日常开发中,线程池是使用非常频繁的一种技术,无论是服务端多线程接收用户请求,还是客户端多线程处理数据,都会用到线程池技术,那么全面的了解线程池的使用.背后的实现原理以及合理的优化线程池的大小等 ...

随机推荐

  1. Linux字符设备驱动file_operations

    struct _file_operations struct _file_operations在Fs.h这个文件里面被定义的,如下所示: struct file_operations { struct ...

  2. windows快捷键命令汇总整理

        访问当前屏幕的设置,打开"设置"栏 按 Windows 徽标键+"i"打开当前屏幕(例如,"开始".桌面或 Windows 应用)的 ...

  3. 用ueditor上传图片、文件等到七牛云存储

    ueditor上传文件,是用数据流的形式上传的. 而七牛云存储官方文档中,只提供了文件路径上传的方式. 但是,仅仅是在官方文档中写了这一种方式. 事实上,利用VS的对象管理器,打开Qiniu的dll, ...

  4. (转)passwordStrength 基于jquery的密码强度检测代码使用介绍

    使用很简单. 代码如下: $('#pass').passwordStrength();  XHTML 代码如下: <p><label>请输入密码:</label>  ...

  5. Linux_x64安装Oracle11g(完整版)

    一.修改操作系统核心参数 在Root用户下执行以下步骤: 1)修改用户的SHELL的限制,修改/etc/security/limits.conf文件 输入命令:vi /etc/security/lim ...

  6. JS正则验证格式

    function test() { var temp = document.getElementById("text1"); //对电子邮件的验证 var myreg = /^([ ...

  7. 有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

    #include <iostream> using namespace std; int main() { int i,j,n,m,k,*p,num[100];k=m=0;   cin&g ...

  8. 在PHP中PDO解决中文乱码问题

    $this->pdo = new PDO($dsn, $user, $password, array(PDO::ATTR_PERSISTENT => true)); $stmt = $th ...

  9. Python学习笔记整理(五)Python中的列表.

    列表和字段,这两种类型几乎是Python所有脚本的主要工作组件.他们都可以在原处进行修改,可以按需求增加或缩短,而且包含任何种类的对象或者被嵌套. 一.列表 列表的主要属性: *任意对象的有序集合 从 ...

  10. 使用redis缓存加索引处理数据库百万级并发

    使用redis缓存加索引处理数据库百万级并发 前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1 ...