基于C++11线程池
- 1.包装线程对象
- class task : public std::tr1::enable_shared_from_this<task>
- {
- public:
- task():exit_(false){}
- task( const task & ) = delete;
- ~task(){}
- task & operator =( const task &) = delete;
- void start();
- void stop()
- {
- exit_ = true;
- sync_.notify_one();
- }
- void set_job( const std::function<void()> & job, const std::string & file, int line)
- {//提交任务
- {
- std::unique_lock<std::mutex> lock(mutex_);
- job_ = job;
- file_ = file;
- line_ = line;
- }
- sync_.notify_one();//通知主线程有任务要运行....
- }
- void print_job(){
- LOG(INFO)<<"sumbit from:"<<file_<<":"<<line_;
- }
- private:
- bool exit_;
- std::mutex mutex_;
- std::condition_variable sync_;
- std::function< void()> job_; //线程运行的任务,线程随意时刻,最多仅仅能运行一个任务。
- std::thread::id id_;
- std::string file_;
- int line_;
- };
void task::start() { auto job_proxy = [this] (){ id_ = std::this_thread::get_id(); while( !exit_ ) { std::unique_lock<std::mutex> lock(mutex_); if( job_ ) {//有任务了,须要运行任务了 try { job_(); //运行任务的代码 }catch( std::exception & e) { }catch(...) { } job_ = std::function<void()>(); //释放任务绑定的资源,主要为闭包捕获的资源,特别是shared_ptr对象. tasks->job_completed( shared_from_this() ); //任务运行完毕,通知线程池 }else{ //没有任务的时候,等待其它线程提交任务。。 sync_.wait(lock); } } }; std::thread t(job_proxy); //创建并启动与task管理的线程 t.detach(); //分离模式,thread对象销毁了。可是其创建的线程还活着。。。}
- 2.线程池管理对象
- class task_pool
- {
- public:
- task_pool(unsigned int pool_size = 128):max_size_(pool_size),stop_all_(true)
- {
- }
- ~task_pool()
- {
- }
- void job_completed( const std::tr1::shared_ptr<task> & t)//回收task对象
- {
- std::lock_guard<std::mutex> lock(mutex_);
- bool need_to_notify = idle_tasks_.empty() && (!wait_for_running_jobs_.empty());
- busying_tasks_.erase(t);
- idle_tasks_.push_back(t);
- LOG(INFO)<<"after job_completed, current idle tasks size:"<< idle_tasks_.size()
- <<" busying tasks size:"<<busying_tasks_.size()
- <<" wait for running jobs size:"<<wait_for_running_jobs_.size();
- if( !busying_tasks_.empty() ){
- (*busying_tasks_.begin())->print_job();
- }
- if( need_to_notify )//任务太多了。之前空暇线程使用完了。有任务在等待运行,须要通知
- {
- sync_.notify_one();
- }
- };
- //提交任务
- void submit_job( const std::function<void()> & job, const std::string file, int line)
- {
- if( stop_all_ )
- {
- return;
- }
- std::lock_guard<std::mutex> lock(mutex_);
- bool need_notify = wait_for_running_jobs_.empty();
- wait_for_running_jobs_.push(std::make_tuple(job,file,line));
- if( need_notify )//等待运行的任务为空时。须要通知,其它情况不须要通知.
- {
- sync_.notify_one();
- }
- }
- void execute_job()
- {
- while(true)
- {
- std::unique_lock<std::mutex> lock(mutex_);
- while(!stop_all_ && wait_for_running_jobs_.empty() )
- {
- //等待其它线程提交任务
- sync_.wait(lock);
- }
- if( stop_all_ )
- {
- return;
- }
- while(!stop_all_ && idle_tasks_.empty())
- {
- //有任务要运行,可是没有空暇线程,等待其它任务运行完毕。
- sync_.wait(lock);
- }
- if( stop_all_ )
- {
- return;
- }
- //有任务。也有空暇线程了
- auto t = get_task();
- auto job =wait_for_running_jobs_.front();
- wait_for_running_jobs_.pop();
- //分发任务到task 线程.
- t->set_job(std::get<0>(job), std::get<1>(job), std::get<2>(job));
- }
- }
- void stop_all()
- {
- std::lock_guard<std::mutex> lock(mutex_);
- stop_all_ = true;
- for( auto t : idle_tasks_ )
- {
- t->stop();
- }
- idle_tasks_.clear();
- for( auto t : busying_tasks_ )
- {
- t->stop();
- }
- while(!wait_for_running_jobs_.empty()){
- wait_for_running_jobs_.pop();
- }
- sync_.notify_one();
- }
- void start()
- {// 初始化启动线程池主线程
- try
- {
- std::thread t( [this]{ execute_job();});
- t.detach();
- stop_all_ = false;
- allocate_tasks();
- }catch( std::exception & e )
- {
- LOG(FATAL) << "start tasks pool ... error"<<e.what();
- }
- }
- protected:
- std::tr1::shared_ptr<task> get_task()
- {
- //获取task对象
- if( ! idle_tasks_.empty() )
- {
- auto t = *idle_tasks_.begin();
- idle_tasks_.pop_front(); //从空暇队列移除
- busying_tasks_.insert(t); //增加忙队列
- return t;
- }
- return std::tr1::shared_ptr<task>();
- }
- void allocate_tasks() //初始化线程池
- {
- for( int i = 0 ; i < max_size_; i ++ )
- {
- std::tr1::shared_ptr<task> t( new task());
- try{
- t->start();
- idle_tasks_.push_back(t);
- }catch( std::exception & e)
- { //超过进程最大线程数限制时,会跑出异常。
- 。。
- break;
- }
- }
- }
- private :
- unsigned int max_size_;
- std::list < std::tr1::shared_ptr<task> > idle_tasks_; //空暇任务队列
- std::set < std::tr1::shared_ptr<task> > busying_tasks_;//正在运行任务的队列
- std::queue< std::tuple< std::function<void()> , std::string, int > > wait_for_running_jobs_; //等待运行的任务
- std::mutex mutex_;
- std::condition_variable sync_;
- bool stop_all_;
- };
- usage
- static task_pool * tasks = nullptr;
- static std::once_flag init_flag;
- static std::once_flag finit_flag;
- void run_job(const std::function<void()> & job , const std::string & file, int line )
- {
- if( tasks != nullptr)
- tasks->submit_job(job, file,line);
- }
- void task_pool_init( unsigned max_task_size)
- {
- std::call_once(init_flag,[max_task_size]{
- tasks = new task_pool(max_task_size);
- tasks->start();
- });
- }
- void task_pool_finit()
- {
- std::call_once(finit_flag,[]{ tasks->stop_all();});
- }
基于C++11线程池的更多相关文章
- 托管C++线程锁实现 c++11线程池
托管C++线程锁实现 最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于 ...
- 简单的C++11线程池实现
线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementation,具体博客可以参见Jakob's D ...
- c++11 线程池学习笔记 (一) 任务队列
学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...
- C++11线程池的实现
什么是线程池 处理大量并发任务,一个请求一个线程来处理请求任务,大量的线程创建和销毁将过多的消耗系统资源,还增加了线程上下文切换开销. 线程池通过在系统中预先创建一定数量的线程,当任务请求到来时从线程 ...
- c++11线程池实现
咳咳.c++11 增加了线程库,从此告别了标准库不支持并发的历史. 然而 c++ 对于多线程的支持还是比較低级,略微高级一点的使用方法都须要自己去实现,譬如线程池.信号量等. 线程池(thread p ...
- 基于hystrix的线程池隔离
hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...
- 开源项目SMSS开发指南(二)——基于libevent的线程池
libevent是一套轻量级的网络库,基于事件驱动开发.能够实现多线程的多路复用和注册事件响应.本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池. 一. 使用指南 监听服 ...
- 基于linux与线程池实现文件管理
项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...
- c++ 11 线程池---完全使用c++ 11新特性
前言: 目前网上的c++线程池资源多是使用老版本或者使用系统接口实现,使用c++ 11新特性的不多,最近研究了一下,实现一个简单版本,可实现任意任意参数函数的调用以及获得返回值. 0 前置知识 首先介 ...
随机推荐
- 模式识别 - libsvm该函数的调用方法 详细说明
libsvm该函数的调用方法 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26261173 须要载入(load)SVM ...
- strtok、strtok_s、strtok_r 字符串切割函数
1.strtok函数 函数原型:char * strtok (char *str, const char * delimiters); 參数:str,待切割的字符串(c-string):delimit ...
- 光流和KLT
一 光流 光流的概念是Gibson在1950年首先提出来的. 它是空间运动物体在观察成像平面上的像素运动的瞬时速度.是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存 ...
- 64位WIN7+oracle11g+plsql
64位WIN7+oracle11g+plsql安装 Posted on 2015-07-28 22:41 算命大师不算卦 阅读(27) 评论(0) 编辑 收藏 上部转自Oracle 11g R2 fo ...
- 使用 CodeIgniter 框架快速开发 PHP 应用(四)
原文:使用 CodeIgniter 框架快速开发 PHP 应用(四) 使用 CI 简化数据库开发你学习CI 是因为你想要使编程更容易和更有生产力.这一章讲述CI的Active Record类. 如果C ...
- ASPNETPager常用属性
<webdiyer:AspNetPager ID="pager" runat="server" class="page" FirstP ...
- DynamicReports 导出Excel 例子
import java.awt.Color; import java.io.FileOutputStream; import java.util.ArrayList; import java.util ...
- NYoj The partial sum problem(简单深搜+优化)
题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=927 代码: #include <stdio.h> #include & ...
- Session与Caching
Session与Caching 在之前的版本中,Session存在于System.Web中,新版ASP.NET 5中由于不在依赖于System.Web.dll库了,所以相应的,Session也就成了A ...
- 【高德地图API】从零开始学高德JS API(六)——坐标转换
原文:[高德地图API]从零开始学高德JS API(六)——坐标转换 摘要:如何从GPS转到谷歌?如何从百度转到高德?这些都是小case.我们还提供,如何将基站cell_id转换为GPS坐标? --- ...