当需要线程等待某个事物时,可以创建一个condition对象,然后通过这个对象来通知那些等待的线程。
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
#include <string>
class Request { /*...*/ };
// A simple job queue class; don't do this, use std::queue
template<typename T>
class JobQueue {
public:
JobQueue( ) {}
~JobQueue( ) {}
void submitJob(const T& x) {
boost::mutex::scoped_lock lock(mutex_);
list_.push_back(x);
workToBeDone_.notify_one( );
}
T getJob( ) {
boost::mutex::scoped_lock lock(mutex_);
workToBeDone_.wait(lock); // Wait until this condition is
// satisfied, then lock the mutex
T tmp = list_.front( );
list_.pop_front( );
return(tmp);
}
private:
std::list<T> list_;
boost::mutex mutex_;
boost::condition workToBeDone_;
};
JobQueue<Request> myJobQueue;
void boss( ) {
for (;;) {
// Get the request from somewhere
Request req;
myJobQueue.submitJob(req);
}
}
void worker( ) {
for (;;) {
Request r(myJobQueue.getJob( ));
// Do something with the job...
}
}
int main( ) {
boost::thread thr1(boss);
boost::thread thr2(worker);
boost::thread thr3(worker);
thr1.join( );
thr2.join( );
thr3.join( );
}
boost::mutex::scoped_lock lock(mutex_);
workToBeDone_.wait(lock);
这两行代码,第一行锁定这个mutex对象。第二行代码解开这个mutex上的锁,然后进行等待或者休眠,直到它的条件得到了满足。这个mutex互斥对象的解锁让其他的线程能够使用这个mutex对象,它们中的某个需要设置这个等待条件,之后通知另外的线程。
notify_all函数,通知那些所有正在等待某个条件变为真的线程,那些线程随后进入运行状态。wait方法做两件事情:它一直等待直到有人在它正等待的condition上调用notify_one或notify_all,然后它就试图锁定相关的mutex。当调用的是notify_all时,尽管多个等待的线程都尽量去获得下一个锁,但谁将获得依赖于这个mutex的类型和使用的优先策略。
一个condition对象能让消费者线程休眠,因此在还没有碰到一个condition时处理器可以去处理别的事情。例如一个web服务器使用一个工作线程池来处理进来的请求。当没有需求进来时,让这些子线程处于等待状态比让它们循环的查询或者睡眠然后偶尔唤醒来检查这个队列,要好很多。
给线程函数传递一个参数:#include <iostream>
#include <string>
#include <functional>
#include <boost/thread/thread.hpp>
// A typedef to make the declarations below easier to read
typedef void (*WorkerFunPtr)(const std::string&);
template<typename FunT, // The type of the function being called
typename ParamT> // The type of its parameter
struct Adapter {
Adapter(FunT f, ParamT& p) : // Construct this adapter and set the
f_(f), p_(&p) {} // members to the function and its arg
void operator( )( ) { // This just calls the function with its arg
f_(*p_);
}
private:
FunT f_;
ParamT* p_; // Use the parameter's address to avoid extra copying
};
void worker(const std::string& s) {
std::cout << s << '\n';
}
int main( ) {
std::string s1 = "This is the first thread!";
std::string s2 = "This is the second thread!";
boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));
boost::thread thr2(Adapter<WorkerFunPtr, std::string>(worker, s2));
thr1.join( );
thr2.join( );
}
使用这个函数适配器类模板,你就可以给线程函数传递参数了。如果你需要传递多个参数,仅需要在这个适配器中增加另一个类型和成员变量。