Boost库实现线程池学习及线程实现的异步调用
A.Boost线程池实现
参考自: Boost库实现线程池实例
原理:使用boost的thread_group存储多个线程,使用bind方法将要处理的函数转换成线程可调用的函数进行执行;使用队列存储待处理任务,利用Mutex实现队列线程安全。
#ifndef MYTHREADPOOL_H
#define MYTHREADPOOL_H #include <iostream>
#include <queue>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
using namespace boost; typedef boost::function<void(void)> MyTask;
//任务队列--noncopyable
class MyTaskQueue : boost::noncopyable
{
private:
std::queue<MyTask> m_taskQueue;
boost::mutex m_mutex;//互斥锁
boost::condition_variable_any m_cond;//条件变量
public:
void push_Task(const MyTask& task){
//加上互斥锁
boost::unique_lock<boost::mutex> lock(m_mutex);
m_taskQueue.push(task);
//通知其他线程启动
m_cond.notify_one();
} MyTask pop_Task(){
//加上互斥锁
boost::unique_lock<boost::mutex> lock(m_mutex);
if(m_taskQueue.empty())
{
//如果队列中没有任务,则等待互斥锁
m_cond.wait(lock);//
}
//指向队列首部
MyTask task(m_taskQueue.front());
//出队列
m_taskQueue.pop();
return task;
}
int get_size()
{
return m_taskQueue.size();
}
}; class MyThreadPool : boost::noncopyable
{
private:
//任务队列
MyTaskQueue m_taskQueue;
//线程组
boost::thread_group m_threadGroup;
int m_threadNum;
/*
volatile 被设计用来修饰被不同线程访问和修改的变量。
volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,
因而编译器生成的可执行码会重新从i的地址读取数据放在k中。
volatile可以保证对特殊地址的稳定访问,不会出错。
*/
volatile bool is_run;
void run(){//线程池中线程的处理函数
while(is_run){
//一直处理线程池的任务
MyTask task = m_taskQueue.pop_Task();
task();//运行bind的函数
}
}
public:
MyThreadPool(int num):m_threadNum(num),is_run(false)//初始化列表
{ }
~MyThreadPool(){
stop();
}
void init()
{
if(m_threadNum <= ) return;
is_run = true;
for (int i=;i<m_threadNum;i++)
{
//生成多个线程,绑定run函数,添加到线程组
m_threadGroup.add_thread(
new boost::thread(boost::bind(&MyThreadPool::run,this)));
}
}
//停止线程池
void stop()
{
is_run = false;
}
//添加任务
void AddNewTask(const MyTask& task){
m_taskQueue.push_Task(task);
}
void wait()
{
m_threadGroup.join_all();//等待线程池处理完成!
}
}; typedef void (*pFunCallBack)(int i);
void CallBackFun(int i)
{
std::cout << i <<" call back!"<<std::endl;
} void ProcFun(int ti,pFunCallBack callback)
{
std::cout<<"I am Task "<<ti<<std::endl;
//task
for (int i=;i<ti*;i++)
{
i*i;
}
if(callback != NULL)callback(ti);
} void CallBackFun2(int i)
{
std::cout << i <<" call back! v2"<<std::endl;
} int ProcFun2(int& ti)
{
std::cout<<"I am Task "<<ti<<std::endl;
//task
for (int i=;i<ti*;i++)
{
i*i;
}
return ti;
} void testThreadPool()
{
MyThreadPool tp();
int taskNum = ;
for (int i=;i<taskNum;i++)
{
MyTask task = boost::bind(ProcFun,i+,CallBackFun);
//放到线程池中处理,bind(f , i) will produce a "nullary" function object that takes no arguments and returns f(i),调用时,可传递任何类型的函数及参数!!!
tp.AddNewTask(task);
} tp.init();
//等待线程池处理完成!
tp.wait();
} #endif
B.基于线程的异步调用实现
原理:使用线程实现异步调用,将耗时的操作放在线程中执行,待其执行完成后,调用回调函数执行后续操作。
//创建一个线程,执行耗时操作,等到操作完成,调用回调函数
void testAsyncCall(int i,pFunCallBack callfun)
{
boost::thread th(boost::bind(ProcFun,i,callfun));
}
void testAsyncCall2(int i)
{
//bind函数嵌套,回调函数 --bind(f, bind(g, _1))(x); // f(g(x))
boost::thread th(boost::bind(CallBackFun2,boost::bind(ProcFun2,i)));
} template <class ParaType,class RetType>
class MyTask2{
typedef boost::function<RetType(ParaType&)> ProcFun;
typedef boost::function<void(RetType)> CallBackFun;
protected:
ProcFun m_procFun;
CallBackFun m_callbackFun;
public:
MyTask2():m_procFun(NULL),m_callbackFun(NULL){ }
MyTask2(ProcFun proc,CallBackFun callback):m_procFun(proc),m_callbackFun(callback){ }
~MyTask2(){ }
void Run(ParaType& para){
if(m_procFun!=NULL && m_callbackFun!=NULL)
{
m_callbackFun(m_procFun(para));
}
}
}; void testAsyncCall3(int para)//使用bind注册执行函数和回调函数
{
MyTask2<int,int> tk(ProcFun2, CallBackFun2);
//tk.Run(para);
MyTask task = boost::bind(&MyTask2<int,int>::Run,tk,para);
boost::thread th(task);
//boost::thread th(boost::bind(&MyTask2<int,int>::Run,tk,para));
}
Boost库实现线程池学习及线程实现的异步调用的更多相关文章
- 【Java多线程】线程池学习
Java线程池学习 众所周知,Java不仅提供了线程,也提供了线程池库给我们使用,那么今天来学学线程池的具体使用以及线程池基本实现原理分析. ThreadPoolExecutor ThreadPool ...
- Java线程池学习
Java线程池学习 Executor框架简介 在Java 5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java ...
- Java线程池学习总结
一 使用线程池的好处 池化技术相比大家已经屡见不鲜了,线程池.数据库连接池.Http 连接池等等都是对这个思想的应用.池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 线程池提供了 ...
- android中的线程池学习笔记
阅读书籍: Android开发艺术探索 Android开发进阶从小工到专家 对线程池原理的简单理解: 创建多个线程并且进行管理,提交的任务会被线程池指派给其中的线程进行执行,通过线程池的统一调度和管理 ...
- Java 线程池学习
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具.真正的线程池接口是ExecutorService. 下面这张图完整描述了线程 ...
- Java线程池学习心得
一.普通线程和线程池的对比 new Thread的弊端如下: a. 每次new Thread新建对象性能差.b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或o ...
- Java线程的学习_线程池
系统启动一个新线程需要很高的成本,因为它涉及与操作系统交互.在这种情况下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时. 线程池在系统启动时即创建大量空闲的线程,程序将 ...
- JDK自带线程池学习
JDK自带线程池 线程池的状态 线程有如下状态 RUNNING状态:Accept new tasks and process queued tasks SHUTDOWN状态:Don't accept ...
- 【温故而知新-万花筒】C# 异步编程 逆变 协变 委托 事件 事件参数 迭代 线程、多线程、线程池、后台线程
额基本脱离了2.0 3.5的时代了.在.net 4.0+ 时代.一切都是辣么简单! 参考文档: http://www.cnblogs.com/linzheng/archive/2012/04/11/2 ...
随机推荐
- RedHat Linux 安装oracle11g
1.准备oracle安装文件Oracle11gR2包含两个文件linux_11gR2_database_1of2.zip和linux_11gR2_database_2of2.zip,将这两个文件通过S ...
- Google搜索技巧-从入门到精通(从此学习进步、工作顺心)
转载:http://www.blogbus.com/koudaizhi-logs/55687286.html 一 GOOGLE简介 Google (www.google.com)是一个搜寻引擎,由某 ...
- Linux下mv命令详解
mv命令格式:mv [选项] 源文件或目录 目标文件或目录 mv命令参数(选项): -b :若需覆盖文件,则覆盖前先行备份. -f :force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖: ...
- BootStrap2学习日记22---点击展开
先看效果: Code: <div class="accordion" id="accordion2"> <div class="ac ...
- solr查询在solrconfig.xml中的配置
<requestHandler name="/select" class="solr.SearchHandler"> <lst name=&q ...
- FormsAuthentication与Session超时时间不一的解决方法
因为FormsAuthentication 和 Session 的cookies不一样,造成了FormsAuthentication 还能进入,而 session已经超时的问题. 最好的办法就是当让F ...
- Android adb not responsing
netstat -aon | findstr "5037" and you will find the process "kadb.exe" that used ...
- 源自梦想 eclipse快捷键整理
Ctrl+1 快速修复(最经典的快捷键,就不用多说了) Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Ctrl+Alt+↑ 复制当前行到上一行(复制增加) ...
- vb6如何将MSHFlexGrid控件中的内容导出为Excel
首先的是是准备工作 需要引用 Microsoft Excel 11.0 Object Library 需要添加控件Mircrosoft Hierarchical FlexGrid Control 6. ...
- Linux命令之cut
cut:文件的每一行剪切字节.字符和字段并将这些字节.字符和字段写至标准输出.如果不指定 File 参数,cut 命令将读取标准输入.必须指定 -b.-c 或 -f 标志之一. 主要参数: -b(by ...