• 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线程池的更多相关文章

  1. 托管C++线程锁实现 c++11线程池

    托管C++线程锁实现   最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于 ...

  2. 简单的C++11线程池实现

    线程池的C++11简单实现,源代码来自Github上作者progschj,地址为:A simple C++11 Thread Pool implementation,具体博客可以参见Jakob's D ...

  3. c++11 线程池学习笔记 (一) 任务队列

    学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...

  4. C++11线程池的实现

    什么是线程池 处理大量并发任务,一个请求一个线程来处理请求任务,大量的线程创建和销毁将过多的消耗系统资源,还增加了线程上下文切换开销. 线程池通过在系统中预先创建一定数量的线程,当任务请求到来时从线程 ...

  5. c++11线程池实现

    咳咳.c++11 增加了线程库,从此告别了标准库不支持并发的历史. 然而 c++ 对于多线程的支持还是比較低级,略微高级一点的使用方法都须要自己去实现,譬如线程池.信号量等. 线程池(thread p ...

  6. 基于hystrix的线程池隔离

    hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...

  7. 开源项目SMSS开发指南(二)——基于libevent的线程池

    libevent是一套轻量级的网络库,基于事件驱动开发.能够实现多线程的多路复用和注册事件响应.本文将介绍libevent的基本功能以及如何利用libevent开发一个线程池. 一. 使用指南 监听服 ...

  8. 基于linux与线程池实现文件管理

    项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...

  9. c++ 11 线程池---完全使用c++ 11新特性

    前言: 目前网上的c++线程池资源多是使用老版本或者使用系统接口实现,使用c++ 11新特性的不多,最近研究了一下,实现一个简单版本,可实现任意任意参数函数的调用以及获得返回值. 0 前置知识 首先介 ...

随机推荐

  1. poj 1004 Dividing

    大意是,从输入六个数 .第i个数代表价值为i的有几个,平均分给两个人 ,明摆着的背包问题,本来以为把他转化为01背包.可是TLe,后来发现是12万的平方还多,所以妥妥的TLE,后来发现这是一个全然背包 ...

  2. 深和学习导航CSS样式

    一个很容易理解,具体导航栏CSS授课风格 诚奉献给朋友: 原文地址:点击这里.

  3. Display Database Image using MS SQL Server 2008 Reporting Services

    原文 Display Database Image using MS SQL Server 2008 Reporting Services With the new release of MS SQL ...

  4. 设计模式 - 迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释

    迭代模式(iterator pattern) Java 迭代器(Iterator) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考迭代器模式(ite ...

  5. 手机号ID开关星号(*)

    .h文件 <span style="font-size:18px;">/** * 转成星号工具 */ @interface AsteriskTool : NSObjec ...

  6. web开发性能优化---UI接口章

    1.尽可能的远div+css设计 DIV+CSS与表相比格优势布局: a.精简代码 采用DIV+CSS设计,页面代码精简.这是为了XHTML了解都知道. 代码精简所带来的直接优点有两点:一是提高蜘蛛爬 ...

  7. SAE+Java+jetty

    SAE的java执行环境jetty如servlet该容器,和开放几乎完全访问.有效支持各种jar包.但对于jdk的要件的版本号是非常严格格,这里的版本号是jdk1.6 SAE利用上传war该方式配置j ...

  8. 第13章 模版方法模式(Template Method)

    原文  第13章 模版方法模式(Template Method) 模板模式 模板模式 举例:模拟下数据库的update方法,先删除在插入. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  9. Android第一次打开应用程序,实现向导界面

    转载请注明出处,谢谢http://blog.csdn.net/harryweasley/article/details/42079167 先说下思路:1.利用Preference存储数据,来记录是否是 ...

  10. int有符号和无符号类型内存 -- C

    /* int 有符号 0xffffffff == -1 0xfffffffe == -2 最小 0x80000000 == -21 4748 3648 最大 0x7fffffff == 21 4748 ...