C++ boost thread库用法详细讲解
无水先生 人气:0一、说明
boost::thread的六种使用方法总结,本文初步介绍线程的函数、构造、执行的详细解释。
二、boost::thread的几个函数
函数 | 功能 |
---|---|
join() | 让主进程等待子线程执行完毕后再继续执行 |
get_id() | 获得线程的 id 号 |
detach() | 标线程就成为了守护线程,驻留后台运行 |
bool joinable() | 是否已经启动,为 join() |
thread::join()是个简单暴力的方法,主线程等待子进程期间什么都不能做,一般情形是主线程创建thread object后做自己的工作而不是简单停留在join上。
thread::join()还会清理子线程相关的内存空间,此后thread object将不再和这个子线程相关了,即thread object不再joinable了,所以join对于一个子线程来说只可以被调用一次,为了实现更精细的线程等待机制,可以使用条件变量等机制。
1、可会合(joinable):这种关系下,主线程需要明确执行等待操作,在子线程结束后,主线程的等待操作执行完毕,子线程和主线程会合,这时主线程继续执行等待操作之后的下一步操作。主线程必须会合可会合的子线程。在主线程的线程函数内部调用子线程对象的wait函数实现,即使子线程能够在主线程之前执行完毕,进入终止态,也必须执行会合操作,否则,系统永远不会主动销毁线程,分配给该线程的系统资源也永远不会释放。
2、相分离(detached):表示子线程无需和主线程会合,也就是相分离的,这种情况下,子线程一旦进入终止状态,这种方式常用在线程数较多的情况下,有时让主线程逐个等待子线程结束,或者让主线程安排每个子线程结束的等待顺序,是很困难或不可能的,所以在并发子线程较多的情况下,这种方式也会经常使用。
三、构造
boost::thread有两个构造函数:
(1)thread():构造一个表示当前执行线程的线程对象;
(2)explicit thread(const boost::function0<void>& threadfunc):
boost::function0<void>可以简单看为:一个无返回(返回void),无参数的函数。这里的函数也可以是类重载operator()构成的函数;该构造函数传入的是函数对象而并非是函数指针,这样一个具有一般函数特性的类也能作为参数传入,在下面有例子。
#include <boost/thread/thread.hpp> #include <iostream> void hello() { std::cout << "Hello world, I''m a thread!" << std::endl; } int main(int argc, char* argv[]) { boost::thread thrd(&hello); thrd.join(); return 0; }
执行结果:
第二种情况:类重载operator()构成的函数创建线程
#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <iostream> boost::mutex io_mutex; struct count { count(int id) : id(id) { } void operator()() { for (int i = 0; i < 10; ++i) { boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": " << i << std::endl; } } int id; }; int main(int argc, char* argv[]) { boost::thread thrd1(count(1)); boost::thread thrd2(count(2)); thrd1.join(); thrd2.join(); return 0; }
运算结果:
第三种情况:在类内部对static函数创建线程
#include <boost/thread/thread.hpp> #include <iostream> class HelloWorld { public: static void hello() { std::cout << "Hello world, I''m a thread!" << std::endl; } static void start() { boost::thread thrd( hello ); thrd.join(); } }; int main(int argc, char* argv[]) { HelloWorld::start(); return 0; }
注意:在这里start()和hello()方法都必须是static方法。因为static方法要比main方法提前加载,所以static方法不能调用一般方法,进一步说,static方法无法调用比它晚加载的方法,切记。 调用时用HelloWorld::start(),说明start在定义类的时候就已经ready,无需在实例化后再调用。
第四种情况:使用boost::bind函数创建线程
#include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <iostream> #include <boost/function.hpp> class HelloWorld { public: void hello() { std::cout << "Hello world, I''m a thread!" << std::endl; } void start() { boost::function0< void> f = boost::bind(&HelloWorld::hello, this); //或boost::function<void()> f = boost::bind(&HelloWorld::hello,this); boost::thread thrd(f); thrd.join(); } }; int main(int argc, char* argv[]) { HelloWorld hello; hello.start(); return 0; }
1)定义函数指针 boost::function0< void> f
2)该指针与HelloWorld::hello函数绑定, boost::bind(&HelloWorld::hello, this);
3)线程与函数指针绑定 boost::thread thrd(f);
4)按照常规,将对象实例化后,调用类函数。
运算结果:
第五种情况:在Singleton模式内部创建线程
#include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <iostream> class HelloWorld { public: void hello() { std::cout << "Hello world, I''m a thread!" << std::endl; } static void start() { boost::thread thrd( boost::bind (&HelloWorld::hello,&HelloWorld::getInstance() ) ) ; thrd.join(); } static HelloWorld& getInstance() { if ( !instance ) instance = new HelloWorld; return *instance; } private: HelloWorld(){} static HelloWorld* instance; }; HelloWorld* HelloWorld::instance = 0; int main(int argc, char* argv[]) { HelloWorld::start(); return 0; }
此例将类对象实例化放在类内部函数中,因此无需显式实例化,就可以调用类内函数。值得研究消化。
第六种情况:在类外用类内部函数创建线程
#include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <string> #include <iostream> class HelloWorld { public: void hello(const std::string& str) { std::cout <<str<< std::endl; } }; int main(int argc, char* argv[]) { HelloWorld obj; boost::thread thrd( boost::bind(&HelloWorld::hello,&obj,"Hello world, I''m a thread!" ) ) ; thrd.join(); return 0; }
线程如何带参数定义?本例就是参考方法!
加载全部内容